From a9179b6eac83bc59c8b03160bb01dec812224296 Mon Sep 17 00:00:00 2001 From: cketti Date: Mon, 14 Aug 2023 14:31:43 +0200 Subject: [PATCH 01/94] Use `OutlinedButton` for `SignInWithGoogleButton` This way the "Sign in with Google" button looks and behaves more like a regular button. --- .../oauth/ui/view/SignInWithGoogleButton.kt | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/view/SignInWithGoogleButton.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/view/SignInWithGoogleButton.kt index 8a5ef0064e..e9529d9a2f 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/view/SignInWithGoogleButton.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/view/SignInWithGoogleButton.kt @@ -3,22 +3,20 @@ package app.k9mail.feature.account.oauth.ui.view import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.LinearOutSlowInEasing import androidx.compose.animation.core.tween -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredWidth import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.ButtonDefaults -import androidx.compose.material.ButtonElevation import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme +import androidx.compose.material.OutlinedButton import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -43,21 +41,19 @@ fun SignInWithGoogleButton( onClick: () -> Unit, modifier: Modifier = Modifier, isLight: Boolean = MaterialTheme.colors.isLight, - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - elevation: ButtonElevation? = ButtonDefaults.elevation(), ) { - Surface( - modifier = Modifier - .border( - width = 1.dp, - color = getBorderColor(isLight), - shape = RoundedCornerShape(8.dp), - ) - .clickable { onClick() } - .then(modifier), - shape = RoundedCornerShape(8.dp), - color = getSurfaceColor(isLight), - elevation = elevation?.elevation(true, interactionSource)?.value ?: 0.dp, + OutlinedButton( + onClick = onClick, + modifier = modifier, + colors = ButtonDefaults.outlinedButtonColors( + contentColor = getTextColor(isLight), + backgroundColor = getSurfaceColor(isLight), + ), + border = BorderStroke( + width = 1.dp, + color = getBorderColor(isLight), + ), + contentPadding = PaddingValues(all = 0.dp), ) { Row( modifier = Modifier -- GitLab From cbf480dbf7f8b7ad0a792c96a6bded443c10c36b Mon Sep 17 00:00:00 2001 From: cketti Date: Fri, 18 Aug 2023 19:58:01 +0200 Subject: [PATCH 02/94] Prepare for version 6.711 --- app/k9mail/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/k9mail/build.gradle.kts b/app/k9mail/build.gradle.kts index 1dfcccd861..530f4ead85 100644 --- a/app/k9mail/build.gradle.kts +++ b/app/k9mail/build.gradle.kts @@ -51,7 +51,7 @@ android { testApplicationId = "com.fsck.k9.tests" versionCode = 37010 - versionName = "6.710" + versionName = "6.711-SNAPSHOT" // Keep in sync with the resource string array "supported_languages" resourceConfigurations.addAll( -- GitLab From 61d4d642a0870f5b32317be769055f5c304971a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 29 Aug 2023 14:39:32 +0200 Subject: [PATCH 03/94] Change line break rule to avoid issues with contributions from Windows --- .editorconfig | 1 + .gitattributes | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 56b592ba81..f76d5403c0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,6 +5,7 @@ charset = utf-8 indent_size = 4 indent_style = space insert_final_newline = true +end_of_line = lf [*.{kt,kts}] ij_kotlin_imports_layout = *,^ diff --git a/.gitattributes b/.gitattributes index 411c077775..6e15da8b7f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,4 @@ -* text=auto eol=lf +* text=auto -*.bat text eol=crlf +*.bat eol=crlf *.jar binary -- GitLab From 27be361bb472a775568e744e3aa180e272387cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 29 Aug 2023 14:58:38 +0200 Subject: [PATCH 04/94] Fix line breaks --- .../demo/src/main/resources/inbox/intro.eml | 18 +- .../resources/turing/turing_award_1966.eml | 168 +- .../resources/turing/turing_award_1967.eml | 70 +- .../resources/turing/turing_award_1968.eml | 80 +- .../resources/turing/turing_award_1970.eml | 70 +- .../resources/turing/turing_award_1971.eml | 64 +- .../resources/turing/turing_award_1972.eml | 54 +- .../resources/turing/turing_award_1975.eml | 60 +- .../resources/turing/turing_award_1977.eml | 78 +- .../resources/turing/turing_award_1978.eml | 72 +- .../resources/turing/turing_award_1979.eml | 66 +- .../resources/turing/turing_award_1981.eml | 102 +- .../resources/turing/turing_award_1983.eml | 92 +- .../resources/turing/turing_award_1987.eml | 84 +- .../resources/turing/turing_award_1991.eml | 88 +- .../resources/turing/turing_award_1996.eml | 56 +- .../jmap_responses/blob/email/email_1.eml | 28 +- .../jmap_responses/blob/email/email_2.eml | 32 +- .../jmap_responses/blob/email/email_3.eml | 18 +- docs/activity_diagram.graphml | 1872 ++++++++--------- 20 files changed, 1586 insertions(+), 1586 deletions(-) diff --git a/backend/demo/src/main/resources/inbox/intro.eml b/backend/demo/src/main/resources/inbox/intro.eml index 8ff767f59a..99021ace03 100644 --- a/backend/demo/src/main/resources/inbox/intro.eml +++ b/backend/demo/src/main/resources/inbox/intro.eml @@ -1,9 +1,9 @@ -MIME-Version: 1.0 -From: "cketti" -Date: Thu, 23 Sep 2021 23:42:00 +0200 -Message-ID: -Subject: Welcome to K-9 Mail -To: User -Content-Type: text/plain; charset=UTF-8 - -Congratulations, you have managed to set up K-9 Mail's demo account. Have fun exploring the app. +MIME-Version: 1.0 +From: "cketti" +Date: Thu, 23 Sep 2021 23:42:00 +0200 +Message-ID: +Subject: Welcome to K-9 Mail +To: User +Content-Type: text/plain; charset=UTF-8 + +Congratulations, you have managed to set up K-9 Mail's demo account. Have fun exploring the app. diff --git a/backend/demo/src/main/resources/turing/turing_award_1966.eml b/backend/demo/src/main/resources/turing/turing_award_1966.eml index 6ad832041d..bed070890c 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1966.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1966.eml @@ -1,84 +1,84 @@ -MIME-Version: 1.0 -From: "Alan J. Perlis" -Date: Sat, 01 Jan 1966 12:00:00 -0400 -Message-ID: -Subject: The Synthesis of Algorithmic Systems -To: Alan Turing -Content-Type: multipart/alternative; boundary=047d7b450b100959e604d85a5320 - ---047d7b450b100959e604d85a5320 -Content-Type: text/plain; charset=UTF-8 - -Both knowledge and wisdom extend man's reach. Knowledge led to computers, -wisdom to chopsticks. Unfortunately our association is overinvolved with -the former. The latter will have to wait for a more sublime day. -On what does and will the fame of Turing rest? That he proved a theorem -showing that for a general computing device--later dubbed a "Turing -machine"--there existed functions which it could not compute? I doubt it. -More likely it rests on the model he invented and employed: his formal -mechanism. -This model has captured the imagination and mobilized the thoughts of a -generation of scientists. It has provided a basis for arguments leading to -theories. His model has proved so useful that its generated activity has -been distributed not only in mathematics, but through several technologies -as well. The arguments that have been employed are not always formal and -the consequent creations not all abstract. -Indeed a most fruitful consequence of the Turing machine has been with the -creation, study and computation of functions which are computable, i.e., in -computer programming. This is not surprising since computers can compute so -much more than we yet know how to specify. -I am sure that all will agree that this model has been enormously valuable. -History will forgive me for not devoting any attention in this lecture to -the effect which Turing had on the development of the general-purpose -digital computer, which has further accelerated our involvement with the -theory and practice of computation. -Since the appearance of Turing's model there have, of course, been others -which have concerned and benefited us in computing. I think, however, that -only one has had an effect as great as Turing's: the formal mechanism -called ALGOL Many will immediately disagree, pointing out that too few of -us have understood it or used it. -While such has, unhappily, been the case, it is not the point. The impulse -given by ALGOL to the development of research in computer science is -relevant while the number of adherents is not. ALGOL, too, has mobilized -our thoughts and has provided us with a basis for our arguments. - ---047d7b450b100959e604d85a5320 -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
Both knowledge and wisdom extend man's reach. Kno= -wledge led to computers, wisdom to chopsticks. Unfortunately our associatio= -n is overinvolved with the former. The latter will have to wait for a more = -sublime day.=C2=A0
-
On what does and will the fame of Turing rest? That he proved a theore= -m showing that for a general computing device--later dubbed a "Turing = -machine"--there existed functions which it could not compute? I doubt = -it. More likely it rests on the model he invented and employed: his formal = -mechanism.=C2=A0
-
This model has captured the imagination and mobilized the thoughts of = -a generation of scientists. It has provided a basis for arguments leading t= -o theories. His model has proved so useful that its generated activity has = -been distributed not only in mathematics, but through several technologies = -as well. The arguments that have been employed are not always formal and th= -e consequent creations not all abstract.=C2=A0
-
Indeed a most fruitful consequence of the Turing machine has been with= - the creation, study and computation of functions which are computable, i.e= -., in computer programming. This is not surprising since computers can comp= -ute so much more than we yet know how to specify.=C2=A0
-
I am sure that all will agree that this model has been enormously valu= -able. History will forgive me for not devoting any attention in this lectur= -e to the effect which Turing had on the development of the general-purpose = -digital computer, which has further accelerated our involvement with the th= -eory and practice of computation.=C2=A0
-
Since the appearance of Turing's model there have, of course, been= - others which have concerned and benefited us in computing. I think, howeve= -r, that only one has had an effect as great as Turing's: the formal mec= -hanism called ALGOL Many will immediately disagree, pointing out that too f= -ew of us have understood it or used it.=C2=A0
-
While such has, unhappily, been the case, it is not the point. The imp= -ulse given by ALGOL to the development of research in computer science is r= -elevant while the number of adherents is not. ALGOL, too, has mobilized our= - thoughts and has provided us with a basis for our arguments.=C2=A0
-
- ---047d7b450b100959e604d85a5320-- +MIME-Version: 1.0 +From: "Alan J. Perlis" +Date: Sat, 01 Jan 1966 12:00:00 -0400 +Message-ID: +Subject: The Synthesis of Algorithmic Systems +To: Alan Turing +Content-Type: multipart/alternative; boundary=047d7b450b100959e604d85a5320 + +--047d7b450b100959e604d85a5320 +Content-Type: text/plain; charset=UTF-8 + +Both knowledge and wisdom extend man's reach. Knowledge led to computers, +wisdom to chopsticks. Unfortunately our association is overinvolved with +the former. The latter will have to wait for a more sublime day. +On what does and will the fame of Turing rest? That he proved a theorem +showing that for a general computing device--later dubbed a "Turing +machine"--there existed functions which it could not compute? I doubt it. +More likely it rests on the model he invented and employed: his formal +mechanism. +This model has captured the imagination and mobilized the thoughts of a +generation of scientists. It has provided a basis for arguments leading to +theories. His model has proved so useful that its generated activity has +been distributed not only in mathematics, but through several technologies +as well. The arguments that have been employed are not always formal and +the consequent creations not all abstract. +Indeed a most fruitful consequence of the Turing machine has been with the +creation, study and computation of functions which are computable, i.e., in +computer programming. This is not surprising since computers can compute so +much more than we yet know how to specify. +I am sure that all will agree that this model has been enormously valuable. +History will forgive me for not devoting any attention in this lecture to +the effect which Turing had on the development of the general-purpose +digital computer, which has further accelerated our involvement with the +theory and practice of computation. +Since the appearance of Turing's model there have, of course, been others +which have concerned and benefited us in computing. I think, however, that +only one has had an effect as great as Turing's: the formal mechanism +called ALGOL Many will immediately disagree, pointing out that too few of +us have understood it or used it. +While such has, unhappily, been the case, it is not the point. The impulse +given by ALGOL to the development of research in computer science is +relevant while the number of adherents is not. ALGOL, too, has mobilized +our thoughts and has provided us with a basis for our arguments. + +--047d7b450b100959e604d85a5320 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
Both knowledge and wisdom extend man's reach. Kno= +wledge led to computers, wisdom to chopsticks. Unfortunately our associatio= +n is overinvolved with the former. The latter will have to wait for a more = +sublime day.=C2=A0
+
On what does and will the fame of Turing rest? That he proved a theore= +m showing that for a general computing device--later dubbed a "Turing = +machine"--there existed functions which it could not compute? I doubt = +it. More likely it rests on the model he invented and employed: his formal = +mechanism.=C2=A0
+
This model has captured the imagination and mobilized the thoughts of = +a generation of scientists. It has provided a basis for arguments leading t= +o theories. His model has proved so useful that its generated activity has = +been distributed not only in mathematics, but through several technologies = +as well. The arguments that have been employed are not always formal and th= +e consequent creations not all abstract.=C2=A0
+
Indeed a most fruitful consequence of the Turing machine has been with= + the creation, study and computation of functions which are computable, i.e= +., in computer programming. This is not surprising since computers can comp= +ute so much more than we yet know how to specify.=C2=A0
+
I am sure that all will agree that this model has been enormously valu= +able. History will forgive me for not devoting any attention in this lectur= +e to the effect which Turing had on the development of the general-purpose = +digital computer, which has further accelerated our involvement with the th= +eory and practice of computation.=C2=A0
+
Since the appearance of Turing's model there have, of course, been= + others which have concerned and benefited us in computing. I think, howeve= +r, that only one has had an effect as great as Turing's: the formal mec= +hanism called ALGOL Many will immediately disagree, pointing out that too f= +ew of us have understood it or used it.=C2=A0
+
While such has, unhappily, been the case, it is not the point. The imp= +ulse given by ALGOL to the development of research in computer science is r= +elevant while the number of adherents is not. ALGOL, too, has mobilized our= + thoughts and has provided us with a basis for our arguments.=C2=A0
+
+ +--047d7b450b100959e604d85a5320-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1967.eml b/backend/demo/src/main/resources/turing/turing_award_1967.eml index a7e3299e19..9326afab9f 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1967.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1967.eml @@ -1,35 +1,35 @@ -MIME-Version: 1.0 -From: "Maurice V. Wilkes" -Date: Wed, 30 Aug 1967 12:00:00 -0400 -Message-ID: -Subject: Computers Then and Now -To: Alan Turing -Content-Type: multipart/alternative; boundary=047d7b5d9bdd0d571a04d85aec30 - ---047d7b5d9bdd0d571a04d85aec30 -Content-Type: text/plain; charset=UTF-8 - -I do not imagine that many of the Turing lecturers who will follow me will -be people who were acquainted with Alan Turing. The work on computable -numbers, for which he is famous, was published in 1936 before digital -computers existed. Later he became one of the first of a distinguished -succession of able mathematicians who have made contributions to the -computer field. He was a colorful figure in the early days of digital -computer development in England, and I would find it difficult to speak of -that period without making some references to him. - ---047d7b5d9bdd0d571a04d85aec30 -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
I do not imagine that many of the Turing lecturers wh= -o will follow me will be people who were acquainted with Alan Turing. The w= -ork on computable numbers, for which he is famous, was published in 1936 be= -fore digital computers existed. Later he became one of the first of a disti= -nguished succession of able mathematicians who have made contributions to t= -he computer field. He was a colorful figure in the early days of digital co= -mputer development in England, and I would find it difficult to speak of th= -at period without making some references to him.
-
- ---047d7b5d9bdd0d571a04d85aec30-- +MIME-Version: 1.0 +From: "Maurice V. Wilkes" +Date: Wed, 30 Aug 1967 12:00:00 -0400 +Message-ID: +Subject: Computers Then and Now +To: Alan Turing +Content-Type: multipart/alternative; boundary=047d7b5d9bdd0d571a04d85aec30 + +--047d7b5d9bdd0d571a04d85aec30 +Content-Type: text/plain; charset=UTF-8 + +I do not imagine that many of the Turing lecturers who will follow me will +be people who were acquainted with Alan Turing. The work on computable +numbers, for which he is famous, was published in 1936 before digital +computers existed. Later he became one of the first of a distinguished +succession of able mathematicians who have made contributions to the +computer field. He was a colorful figure in the early days of digital +computer development in England, and I would find it difficult to speak of +that period without making some references to him. + +--047d7b5d9bdd0d571a04d85aec30 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
I do not imagine that many of the Turing lecturers wh= +o will follow me will be people who were acquainted with Alan Turing. The w= +ork on computable numbers, for which he is famous, was published in 1936 be= +fore digital computers existed. Later he became one of the first of a disti= +nguished succession of able mathematicians who have made contributions to t= +he computer field. He was a colorful figure in the early days of digital co= +mputer development in England, and I would find it difficult to speak of th= +at period without making some references to him.
+
+ +--047d7b5d9bdd0d571a04d85aec30-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1968.eml b/backend/demo/src/main/resources/turing/turing_award_1968.eml index 274260c0ee..f9b989ad41 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1968.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1968.eml @@ -1,40 +1,40 @@ -MIME-Version: 1.0 -From: Richard Hamming -Date: Tue, 27 Aug 1968 12:00:00 -0400 -Message-ID: -Subject: One Man's View of Computer Science -To: Alan Turing -Content-Type: multipart/alternative; boundary=089e01227b30f6f60004d85af2ae - ---089e01227b30f6f60004d85af2ae -Content-Type: text/plain; charset=UTF-8 - -Let me begin with a few personal words. When one is notified that he has -been elected the ACM Turing lecturer for the year, he is at first -surprised--especially is the nonacademic person surprised by an ACM award. -After a little while the surprise is replaced by a feeling of pleasure. -Still later comes a feeling of "Why me?" With all that has been done and is -being done in computing, why single out me and my work? Well, I suppose -that it has to happen to someone each year, and this -time I am the lucky person. Anyway, let me thank you for the honor you have -given to me and by inference to the Bell Telephone Laboratories where I -work and which has made possible so much of what I have done. - ---089e01227b30f6f60004d85af2ae -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
Let me begin with a few personal words. When one is n= -otified that he has been elected the ACM Turing lecturer for the year, he i= -s at first surprised--especially is the nonacademic person surprised by an = -ACM award. After a little while the surprise is replaced by a feeling of pl= -easure. Still later comes a feeling of "Why me?" With all that ha= -s been done and is being done in computing, why single out me and my work? = -Well, I suppose that it has to happen to someone each year, and this=C2=A0<= -/div> -
time I am the lucky person. Anyway, let me thank you for the honor you= - have given to me and by inference to the Bell Telephone Laboratories where= - I work and which has made possible so much of what I have done.
- ---089e01227b30f6f60004d85af2ae-- +MIME-Version: 1.0 +From: Richard Hamming +Date: Tue, 27 Aug 1968 12:00:00 -0400 +Message-ID: +Subject: One Man's View of Computer Science +To: Alan Turing +Content-Type: multipart/alternative; boundary=089e01227b30f6f60004d85af2ae + +--089e01227b30f6f60004d85af2ae +Content-Type: text/plain; charset=UTF-8 + +Let me begin with a few personal words. When one is notified that he has +been elected the ACM Turing lecturer for the year, he is at first +surprised--especially is the nonacademic person surprised by an ACM award. +After a little while the surprise is replaced by a feeling of pleasure. +Still later comes a feeling of "Why me?" With all that has been done and is +being done in computing, why single out me and my work? Well, I suppose +that it has to happen to someone each year, and this +time I am the lucky person. Anyway, let me thank you for the honor you have +given to me and by inference to the Bell Telephone Laboratories where I +work and which has made possible so much of what I have done. + +--089e01227b30f6f60004d85af2ae +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
Let me begin with a few personal words. When one is n= +otified that he has been elected the ACM Turing lecturer for the year, he i= +s at first surprised--especially is the nonacademic person surprised by an = +ACM award. After a little while the surprise is replaced by a feeling of pl= +easure. Still later comes a feeling of "Why me?" With all that ha= +s been done and is being done in computing, why single out me and my work? = +Well, I suppose that it has to happen to someone each year, and this=C2=A0<= +/div> +
time I am the lucky person. Anyway, let me thank you for the honor you= + have given to me and by inference to the Bell Telephone Laboratories where= + I work and which has made possible so much of what I have done.
+ +--089e01227b30f6f60004d85af2ae-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1970.eml b/backend/demo/src/main/resources/turing/turing_award_1970.eml index 811130ac1d..98edc18e6d 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1970.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1970.eml @@ -1,35 +1,35 @@ -MIME-Version: 1.0 -From: "James H. Wilkinson" -Date: Tue, 01 Sep 1970 12:00:00 -0400 -Message-ID: -Subject: Some Comments from a Numerical Analyst -To: Alan Turing -Content-Type: multipart/alternative; boundary=047d7b5d9bdd9697d504d85ac65f - ---047d7b5d9bdd9697d504d85ac65f -Content-Type: text/plain; charset=UTF-8 - -When at last I recovered from the feeling of shocked elation at being -invited to give the 1970 Turing Award Lecture, I became aware that I must -indeed prepare an appropriate lecture. There appears to be a tradition that -a Turing Lecturer should decide for himself what is expected from him, and -probably for this reason previous lectures have differed considerably in -style and content. However, it was made quite clear that I was to give an -after-luncheon speech and that I would not have the benefit of an overhead -projector or a blackboard. - ---047d7b5d9bdd9697d504d85ac65f -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
When at last I recovered from the feeling of shocked = -elation at being invited to give the 1970 Turing Award Lecture, I became aw= -are that I must indeed prepare an appropriate lecture. There appears to be = -a tradition that a Turing Lecturer should decide for himself what is expect= -ed from him, and probably for this reason previous lectures have differed c= -onsiderably in style and content. However, it was made quite clear that I w= -as to give an after-luncheon speech and that I would not have the benefit o= -f an overhead projector or a blackboard.
-
- ---047d7b5d9bdd9697d504d85ac65f-- +MIME-Version: 1.0 +From: "James H. Wilkinson" +Date: Tue, 01 Sep 1970 12:00:00 -0400 +Message-ID: +Subject: Some Comments from a Numerical Analyst +To: Alan Turing +Content-Type: multipart/alternative; boundary=047d7b5d9bdd9697d504d85ac65f + +--047d7b5d9bdd9697d504d85ac65f +Content-Type: text/plain; charset=UTF-8 + +When at last I recovered from the feeling of shocked elation at being +invited to give the 1970 Turing Award Lecture, I became aware that I must +indeed prepare an appropriate lecture. There appears to be a tradition that +a Turing Lecturer should decide for himself what is expected from him, and +probably for this reason previous lectures have differed considerably in +style and content. However, it was made quite clear that I was to give an +after-luncheon speech and that I would not have the benefit of an overhead +projector or a blackboard. + +--047d7b5d9bdd9697d504d85ac65f +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
When at last I recovered from the feeling of shocked = +elation at being invited to give the 1970 Turing Award Lecture, I became aw= +are that I must indeed prepare an appropriate lecture. There appears to be = +a tradition that a Turing Lecturer should decide for himself what is expect= +ed from him, and probably for this reason previous lectures have differed c= +onsiderably in style and content. However, it was made quite clear that I w= +as to give an after-luncheon speech and that I would not have the benefit o= +f an overhead projector or a blackboard.
+
+ +--047d7b5d9bdd9697d504d85ac65f-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1971.eml b/backend/demo/src/main/resources/turing/turing_award_1971.eml index 387f995770..00b5b495e0 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1971.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1971.eml @@ -1,32 +1,32 @@ -MIME-Version: 1.0 -From: John McCarthy -Date: Fri, 01 Jan 1971 12:00:00 -0400 -Message-ID: -Subject: Generality in Artificial Intelligence -To: Alan Turing -Content-Type: multipart/alternative; boundary=089e01030106b6942904d85ad870 - ---089e01030106b6942904d85ad870 -Content-Type: text/plain; charset=UTF-8 - -Postscript -My 1971 Turing Award Lecture was entitled "Generality in Artificial -Intelligence." The topic turned out to have been overambitious in that I -discovered that I was unable to put my thoughts on the subject in a -satisfactory written form at that time. It would have been better to have -reviewed previous work rather than attempt something new, but such wasn't -my custom at that time. - ---089e01030106b6942904d85ad870 -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
Postscript
My 1971 Turing Award Lecture was= - entitled "Generality in Artificial Intelligence." The topic turn= -ed out to have been overambitious in that I discovered that I was unable to= - put my thoughts on the subject in a satisfactory written form at that time= -. It would have been better to have reviewed previous work rather than atte= -mpt something new, but such wasn't my custom at that time.
-
- ---089e01030106b6942904d85ad870-- +MIME-Version: 1.0 +From: John McCarthy +Date: Fri, 01 Jan 1971 12:00:00 -0400 +Message-ID: +Subject: Generality in Artificial Intelligence +To: Alan Turing +Content-Type: multipart/alternative; boundary=089e01030106b6942904d85ad870 + +--089e01030106b6942904d85ad870 +Content-Type: text/plain; charset=UTF-8 + +Postscript +My 1971 Turing Award Lecture was entitled "Generality in Artificial +Intelligence." The topic turned out to have been overambitious in that I +discovered that I was unable to put my thoughts on the subject in a +satisfactory written form at that time. It would have been better to have +reviewed previous work rather than attempt something new, but such wasn't +my custom at that time. + +--089e01030106b6942904d85ad870 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
Postscript
My 1971 Turing Award Lecture was= + entitled "Generality in Artificial Intelligence." The topic turn= +ed out to have been overambitious in that I discovered that I was unable to= + put my thoughts on the subject in a satisfactory written form at that time= +. It would have been better to have reviewed previous work rather than atte= +mpt something new, but such wasn't my custom at that time.
+
+ +--089e01030106b6942904d85ad870-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1972.eml b/backend/demo/src/main/resources/turing/turing_award_1972.eml index 9c533bdbd9..676c77c004 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1972.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1972.eml @@ -1,27 +1,27 @@ -MIME-Version: 1.0 -From: "Edsger W. Dijkstra" -Date: Mon, 02 Aug 1972 12:00:00 -0500 -Message-ID: -Subject: The Humble Programmer -To: Alan Turing -Content-Type: text/plain; charset=UTF-8; format=flowed - -As a result of a long sequence of coincidences I entered the programming -profession officially on the first spring morning of 1952, and as far as -I have been able to trace, I was the first Dutchman to do so in my -country. In retrospect the most amazing thing is the slowness with which, -at least in my part of the world, the programming profession emerged, a -slowness which is now hard to believe. But I am grateful for two vivid -recollections from that period that establish that slowness beyond any -doubt. - -After having programmed for some three years, I had a discussion with -van Wijngaarden, who was then my boss at the Mathematical Centre in -Amsterdam - a discussion for which I shall remain grateful to him -as long as I live. The point was that I was supposed to study theoretical -physics at the University of Leiden simultaneously, and as I found the -two activities harder and harder to combine, I had to make up my -mind, either to stop programming and become a real, respectable theoretical -physicist, or to carry my study of physics to a formal completion only, -with a minimum of effort, and to become..., yes what? A programmer? -But was that a respectable profession? After all, what was programming? +MIME-Version: 1.0 +From: "Edsger W. Dijkstra" +Date: Mon, 02 Aug 1972 12:00:00 -0500 +Message-ID: +Subject: The Humble Programmer +To: Alan Turing +Content-Type: text/plain; charset=UTF-8; format=flowed + +As a result of a long sequence of coincidences I entered the programming +profession officially on the first spring morning of 1952, and as far as +I have been able to trace, I was the first Dutchman to do so in my +country. In retrospect the most amazing thing is the slowness with which, +at least in my part of the world, the programming profession emerged, a +slowness which is now hard to believe. But I am grateful for two vivid +recollections from that period that establish that slowness beyond any +doubt. + +After having programmed for some three years, I had a discussion with +van Wijngaarden, who was then my boss at the Mathematical Centre in +Amsterdam - a discussion for which I shall remain grateful to him +as long as I live. The point was that I was supposed to study theoretical +physics at the University of Leiden simultaneously, and as I found the +two activities harder and harder to combine, I had to make up my +mind, either to stop programming and become a real, respectable theoretical +physicist, or to carry my study of physics to a formal completion only, +with a minimum of effort, and to become..., yes what? A programmer? +But was that a respectable profession? After all, what was programming? diff --git a/backend/demo/src/main/resources/turing/turing_award_1975.eml b/backend/demo/src/main/resources/turing/turing_award_1975.eml index f91e9ec5c6..c5c835e8fc 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1975.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1975.eml @@ -1,30 +1,30 @@ -MIME-Version: 1.0 -From: Allen Newell -Cc: Herbert Simon -Date: Mon, 20 Oct 1975 12:00:00 -0500 -Message-ID: -Subject: Computer Science as Empirical Inquiry: Symbols and Search -To: Alan Turing -Content-Type: multipart/alternative; boundary=047d7b450b1092035304d85abf33 - ---047d7b450b1092035304d85abf33 -Content-Type: text/plain; charset=UTF-8 - -Computer science is the study of the phenomena surrounding computers. The -founders of this society understood this very well when they called -themselves the Association for Computing Machinery. The machine---not just -the hardware, but the programmed, living machine--is the organism we study. - ---047d7b450b1092035304d85abf33 -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
Computer science is the study of the phenomena surrounding= - computers. The founders of this society understood this very well when the= -y called themselves the Association for Computing Machinery. The machine---= -not just the hardware, but the programmed, living machine--is the organism = -we study.
- -
- ---047d7b450b1092035304d85abf33-- +MIME-Version: 1.0 +From: Allen Newell +Cc: Herbert Simon +Date: Mon, 20 Oct 1975 12:00:00 -0500 +Message-ID: +Subject: Computer Science as Empirical Inquiry: Symbols and Search +To: Alan Turing +Content-Type: multipart/alternative; boundary=047d7b450b1092035304d85abf33 + +--047d7b450b1092035304d85abf33 +Content-Type: text/plain; charset=UTF-8 + +Computer science is the study of the phenomena surrounding computers. The +founders of this society understood this very well when they called +themselves the Association for Computing Machinery. The machine---not just +the hardware, but the programmed, living machine--is the organism we study. + +--047d7b450b1092035304d85abf33 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
Computer science is the study of the phenomena surrounding= + computers. The founders of this society understood this very well when the= +y called themselves the Association for Computing Machinery. The machine---= +not just the hardware, but the programmed, living machine--is the organism = +we study.
+ +
+ +--047d7b450b1092035304d85abf33-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1977.eml b/backend/demo/src/main/resources/turing/turing_award_1977.eml index 51cafd472a..74cac780b5 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1977.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1977.eml @@ -1,39 +1,39 @@ -MIME-Version: 1.0 -From: "John W. Backus" -Date: Mon, 17 Oct 1977 12:00:00 -0700 -Message-ID: -Subject: Can Programming Be Liberated from the von Neumann Style? A Functional - Style and Its Algebra of Programs -To: Alan Turing -Content-Type: multipart/alternative; boundary=047d7b5d9bdd8a36e804d85ade47 - ---047d7b5d9bdd8a36e804d85ade47 -Content-Type: text/plain; charset=UTF-8 - -Conventional programming languages are growing ever more enormous, but not -stronger. Inherent defects at the most basic level cause them to be both -fat and weak: their primitive word-at-a-time style of programming inherited -from their common ancestor--the von Neumann computer, their close coupling -of semantics to state transitions, their division of programming into a -world of expressions and a world of statements, their inability to -effectively use powerful combining forms for building new programs from -existing ones, and their lack of useful mathematical properties for -reasoning about -programs. - ---047d7b5d9bdd8a36e804d85ade47 -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
Conventional programming languages are growing ever m= -ore enormous, but not stronger. Inherent defects at the most basic level ca= -use them to be both fat and weak: their primitive word-at-a-time style of p= -rogramming inherited from their common ancestor--the von Neumann computer, = -their close coupling of semantics to state transitions, their division of p= -rogramming into a world of expressions and a world of statements, their ina= -bility to effectively use powerful combining forms for building new program= -s from existing ones, and their lack of useful mathematical properties for = -reasoning about=C2=A0
-
programs.
- ---047d7b5d9bdd8a36e804d85ade47-- +MIME-Version: 1.0 +From: "John W. Backus" +Date: Mon, 17 Oct 1977 12:00:00 -0700 +Message-ID: +Subject: Can Programming Be Liberated from the von Neumann Style? A Functional + Style and Its Algebra of Programs +To: Alan Turing +Content-Type: multipart/alternative; boundary=047d7b5d9bdd8a36e804d85ade47 + +--047d7b5d9bdd8a36e804d85ade47 +Content-Type: text/plain; charset=UTF-8 + +Conventional programming languages are growing ever more enormous, but not +stronger. Inherent defects at the most basic level cause them to be both +fat and weak: their primitive word-at-a-time style of programming inherited +from their common ancestor--the von Neumann computer, their close coupling +of semantics to state transitions, their division of programming into a +world of expressions and a world of statements, their inability to +effectively use powerful combining forms for building new programs from +existing ones, and their lack of useful mathematical properties for +reasoning about +programs. + +--047d7b5d9bdd8a36e804d85ade47 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
Conventional programming languages are growing ever m= +ore enormous, but not stronger. Inherent defects at the most basic level ca= +use them to be both fat and weak: their primitive word-at-a-time style of p= +rogramming inherited from their common ancestor--the von Neumann computer, = +their close coupling of semantics to state transitions, their division of p= +rogramming into a world of expressions and a world of statements, their ina= +bility to effectively use powerful combining forms for building new program= +s from existing ones, and their lack of useful mathematical properties for = +reasoning about=C2=A0
+
programs.
+ +--047d7b5d9bdd8a36e804d85ade47-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1978.eml b/backend/demo/src/main/resources/turing/turing_award_1978.eml index a1001324ab..6dc52b24d7 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1978.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1978.eml @@ -1,36 +1,36 @@ -MIME-Version: 1.0 -From: Robert Floyd -Date: Mon, 04 Dec 1978 12:00:00 -0500 -Message-ID: -Subject: The Paradigms of Programming -To: Alan Turing -Content-Type: multipart/alternative; boundary=089e0118419206e64304d85af860 - ---089e0118419206e64304d85af860 -Content-Type: text/plain; charset=UTF-8 - -Today I want to talk about the paradigms of programming, how they affect -our success as designers of computer programs, how they should be taught, -and how they should be embodied in our programming languages. -A familiar example of a paradigm of programming is the technique of -structured programming, which appears to be the dominant paradigm in most -current treatments of programming methodology. Structured programming, as -formulated by Dijkstra, Wirth, and Parnas, among others, consists of two -phases. - ---089e0118419206e64304d85af860 -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
Today I want to talk about the paradigms of programmi= -ng, how they affect our success as designers of computer programs, how they= - should be taught, and how they should be embodied in our programming langu= -ages.=C2=A0
-
A familiar example of a paradigm of programming is the technique of st= -ructured programming, which appears to be the dominant paradigm in most cur= -rent treatments of programming methodology. Structured programming, as form= -ulated by Dijkstra, Wirth, and Parnas, among others, consists of two phases= -.=C2=A0
-
- ---089e0118419206e64304d85af860-- +MIME-Version: 1.0 +From: Robert Floyd +Date: Mon, 04 Dec 1978 12:00:00 -0500 +Message-ID: +Subject: The Paradigms of Programming +To: Alan Turing +Content-Type: multipart/alternative; boundary=089e0118419206e64304d85af860 + +--089e0118419206e64304d85af860 +Content-Type: text/plain; charset=UTF-8 + +Today I want to talk about the paradigms of programming, how they affect +our success as designers of computer programs, how they should be taught, +and how they should be embodied in our programming languages. +A familiar example of a paradigm of programming is the technique of +structured programming, which appears to be the dominant paradigm in most +current treatments of programming methodology. Structured programming, as +formulated by Dijkstra, Wirth, and Parnas, among others, consists of two +phases. + +--089e0118419206e64304d85af860 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
Today I want to talk about the paradigms of programmi= +ng, how they affect our success as designers of computer programs, how they= + should be taught, and how they should be embodied in our programming langu= +ages.=C2=A0
+
A familiar example of a paradigm of programming is the technique of st= +ructured programming, which appears to be the dominant paradigm in most cur= +rent treatments of programming methodology. Structured programming, as form= +ulated by Dijkstra, Wirth, and Parnas, among others, consists of two phases= +.=C2=A0
+
+ +--089e0118419206e64304d85af860-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1979.eml b/backend/demo/src/main/resources/turing/turing_award_1979.eml index 9322643ae4..e61c5d3b10 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1979.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1979.eml @@ -1,33 +1,33 @@ -MIME-Version: 1.0 -From: "Kenneth E. Iverson" -Date: Mon, 29 Oct 1979 12:00:00 -0500 -Message-ID: -Subject: Notation as a Tool of Thought -To: Alan Turing -Content-Type: multipart/alternative; boundary=20cf30549cad76254e04d85ae4df - ---20cf30549cad76254e04d85ae4df -Content-Type: text/plain; charset=UTF-8 - -The importance of nomenclature, notation, and language as tools of thought -has long been recognized. In chemistry and in botany, for example, the -establishment of systems of nomenclature by Lavoisier and Linnaeus did much -to stimulate and to channel later investigation. Concerning language, -George Boole in his Laws off Thought asserted "That language is an -instrument of human reason, and not merely a medium for the expression of -thought, is a truth generally admitted." - ---20cf30549cad76254e04d85ae4df -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
The importance of nomenclature, notation, and languag= -e as tools of thought has long been recognized. In chemistry and in botany,= - for example, the establishment of systems of nomenclature by Lavoisier and= - Linnaeus did much to stimulate and to channel later investigation. Concern= -ing language, George Boole in his Laws off Thought asserted "That lang= -uage is an instrument of human reason, and not merely a medium for the expr= -ession of thought, is a truth generally admitted."
-
- ---20cf30549cad76254e04d85ae4df-- +MIME-Version: 1.0 +From: "Kenneth E. Iverson" +Date: Mon, 29 Oct 1979 12:00:00 -0500 +Message-ID: +Subject: Notation as a Tool of Thought +To: Alan Turing +Content-Type: multipart/alternative; boundary=20cf30549cad76254e04d85ae4df + +--20cf30549cad76254e04d85ae4df +Content-Type: text/plain; charset=UTF-8 + +The importance of nomenclature, notation, and language as tools of thought +has long been recognized. In chemistry and in botany, for example, the +establishment of systems of nomenclature by Lavoisier and Linnaeus did much +to stimulate and to channel later investigation. Concerning language, +George Boole in his Laws off Thought asserted "That language is an +instrument of human reason, and not merely a medium for the expression of +thought, is a truth generally admitted." + +--20cf30549cad76254e04d85ae4df +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
The importance of nomenclature, notation, and languag= +e as tools of thought has long been recognized. In chemistry and in botany,= + for example, the establishment of systems of nomenclature by Lavoisier and= + Linnaeus did much to stimulate and to channel later investigation. Concern= +ing language, George Boole in his Laws off Thought asserted "That lang= +uage is an instrument of human reason, and not merely a medium for the expr= +ession of thought, is a truth generally admitted."
+
+ +--20cf30549cad76254e04d85ae4df-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1981.eml b/backend/demo/src/main/resources/turing/turing_award_1981.eml index 6dd8e51d42..92fb6efa39 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1981.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1981.eml @@ -1,51 +1,51 @@ -MIME-Version: 1.0 -From: "Edgar F. Codd" -Date: Wed, 11 Nov 1981 12:00:00 -0800 -Message-ID: -Subject: Relational Database: A Practical Foundation for Productivity -To: Alan Turing -Content-Type: multipart/alternative; boundary=047d7bfd026c782f2404d85ab4b8 - ---047d7bfd026c782f2404d85ab4b8 -Content-Type: text/plain; charset=UTF-8 - -It is well known that the growth in demands from end users for new -applications is outstripping the capability of data processing departments -to implement the corresponding application programs. There are two -complementary approaches to attacking this problem (and both approaches are -needed): one is to put end users into direct touch with the information -stored in computers; the other is to increase the productivity of data -processing professionals in the development of application programs. It is -less well known that a single technology, relational database management, -provides a practical foundation for both approaches. It is explained why -this -is so. -While developing this productivity theme, it is noted that the time has -come to draw a very sharp line between relational and non-relational -database systems, so that the label "relational" will not be used in -misleading ways. -The key to drawing this line is something called a "relational processing -capability." - ---047d7bfd026c782f2404d85ab4b8 -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
It is well known that the growth in demands from end = -users for new applications is outstripping the capability of data processin= -g departments to implement the corresponding application programs. There ar= -e two complementary approaches to attacking this problem (and both approach= -es are needed): one is to put end users into direct touch with the informat= -ion stored in computers; the other is to increase the productivity of data = -processing professionals in the development of application programs. It is = -less well known that a single technology, relational database management, p= -rovides a practical foundation for both approaches. It is explained why thi= -s=C2=A0
-
is so.=C2=A0
While developing this productivity theme, = -it is noted that the time has come to draw a very sharp line between relati= -onal and non-relational database systems, so that the label "relationa= -l" will not be used in misleading ways.=C2=A0
-
The key to drawing this line is something called a "relational pr= -ocessing capability."
- ---047d7bfd026c782f2404d85ab4b8-- +MIME-Version: 1.0 +From: "Edgar F. Codd" +Date: Wed, 11 Nov 1981 12:00:00 -0800 +Message-ID: +Subject: Relational Database: A Practical Foundation for Productivity +To: Alan Turing +Content-Type: multipart/alternative; boundary=047d7bfd026c782f2404d85ab4b8 + +--047d7bfd026c782f2404d85ab4b8 +Content-Type: text/plain; charset=UTF-8 + +It is well known that the growth in demands from end users for new +applications is outstripping the capability of data processing departments +to implement the corresponding application programs. There are two +complementary approaches to attacking this problem (and both approaches are +needed): one is to put end users into direct touch with the information +stored in computers; the other is to increase the productivity of data +processing professionals in the development of application programs. It is +less well known that a single technology, relational database management, +provides a practical foundation for both approaches. It is explained why +this +is so. +While developing this productivity theme, it is noted that the time has +come to draw a very sharp line between relational and non-relational +database systems, so that the label "relational" will not be used in +misleading ways. +The key to drawing this line is something called a "relational processing +capability." + +--047d7bfd026c782f2404d85ab4b8 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
It is well known that the growth in demands from end = +users for new applications is outstripping the capability of data processin= +g departments to implement the corresponding application programs. There ar= +e two complementary approaches to attacking this problem (and both approach= +es are needed): one is to put end users into direct touch with the informat= +ion stored in computers; the other is to increase the productivity of data = +processing professionals in the development of application programs. It is = +less well known that a single technology, relational database management, p= +rovides a practical foundation for both approaches. It is explained why thi= +s=C2=A0
+
is so.=C2=A0
While developing this productivity theme, = +it is noted that the time has come to draw a very sharp line between relati= +onal and non-relational database systems, so that the label "relationa= +l" will not be used in misleading ways.=C2=A0
+
The key to drawing this line is something called a "relational pr= +ocessing capability."
+ +--047d7bfd026c782f2404d85ab4b8-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1983.eml b/backend/demo/src/main/resources/turing/turing_award_1983.eml index 798cdf5216..344f752c2f 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1983.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1983.eml @@ -1,46 +1,46 @@ -MIME-Version: 1.0 -From: Dennis Ritchie -Date: Mon, 24 Oct 1983 12:00:00 -0400 -Message-ID: -Subject: Reflections on Software Research -To: Alan Turing -Content-Type: multipart/alternative; boundary=bcaec54fbb2250035a04d85aabcd - ---bcaec54fbb2250035a04d85aabcd -Content-Type: text/plain; charset=UTF-8 - -The UNIX operating system has suddenly become news, but it is not new. It -began in 1969 when Ken Thompson discovered a little-used PDP-7 computer and -set out to fashion a computing environment that he liked, His work soon -attracted me; I joined in the enterprise, though most of the ideas, and -most of the work for that matter, were his. Before long, others from our -group in the research area of AT&T Bell Laboratories were using the system; -Joe Ossanna, Doug Mcllroy, and -Bob Morris were especially enthusiastic critics and contributors, tn 1971, -we acquired a PDP-11, and by the end of that year we were supporting our -first real users: three typists entering patent applications. In 1973, the -system was rewritten in the C language, and in that year, too, it was first -described publicly at the Operating Systems Principles conference; the -resulting paper appeared in Communications of the ACM the next year. - ---bcaec54fbb2250035a04d85aabcd -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
The UNIX operating system has suddenly become news, b= -ut it is not new. It began in 1969 when Ken Thompson discovered a little-us= -ed PDP-7 computer and set out to fashion a computing environment that he li= -ked, His work soon attracted me; I joined in the enterprise, though most of= - the ideas, and most of the work for that matter, were his. Before long, ot= -hers from our group in the research area of AT&T Bell Laboratories were= - using the system; Joe Ossanna, Doug Mcllroy, and=C2=A0
-
Bob Morris were especially enthusiastic critics and contributors, tn 1= -971, we acquired a PDP-11, and by the end of that year we were supporting o= -ur first real users: three typists entering patent applications. In 1973, t= -he system was rewritten in the C language, and in that year, too, it was fi= -rst described publicly at the Operating Systems Principles conference; the = -resulting paper appeared in Communications of the ACM the next year.=C2=A0<= -/div> -
- ---bcaec54fbb2250035a04d85aabcd-- +MIME-Version: 1.0 +From: Dennis Ritchie +Date: Mon, 24 Oct 1983 12:00:00 -0400 +Message-ID: +Subject: Reflections on Software Research +To: Alan Turing +Content-Type: multipart/alternative; boundary=bcaec54fbb2250035a04d85aabcd + +--bcaec54fbb2250035a04d85aabcd +Content-Type: text/plain; charset=UTF-8 + +The UNIX operating system has suddenly become news, but it is not new. It +began in 1969 when Ken Thompson discovered a little-used PDP-7 computer and +set out to fashion a computing environment that he liked, His work soon +attracted me; I joined in the enterprise, though most of the ideas, and +most of the work for that matter, were his. Before long, others from our +group in the research area of AT&T Bell Laboratories were using the system; +Joe Ossanna, Doug Mcllroy, and +Bob Morris were especially enthusiastic critics and contributors, tn 1971, +we acquired a PDP-11, and by the end of that year we were supporting our +first real users: three typists entering patent applications. In 1973, the +system was rewritten in the C language, and in that year, too, it was first +described publicly at the Operating Systems Principles conference; the +resulting paper appeared in Communications of the ACM the next year. + +--bcaec54fbb2250035a04d85aabcd +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
The UNIX operating system has suddenly become news, b= +ut it is not new. It began in 1969 when Ken Thompson discovered a little-us= +ed PDP-7 computer and set out to fashion a computing environment that he li= +ked, His work soon attracted me; I joined in the enterprise, though most of= + the ideas, and most of the work for that matter, were his. Before long, ot= +hers from our group in the research area of AT&T Bell Laboratories were= + using the system; Joe Ossanna, Doug Mcllroy, and=C2=A0
+
Bob Morris were especially enthusiastic critics and contributors, tn 1= +971, we acquired a PDP-11, and by the end of that year we were supporting o= +ur first real users: three typists entering patent applications. In 1973, t= +he system was rewritten in the C language, and in that year, too, it was fi= +rst described publicly at the Operating Systems Principles conference; the = +resulting paper appeared in Communications of the ACM the next year.=C2=A0<= +/div> +
+ +--bcaec54fbb2250035a04d85aabcd-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1987.eml b/backend/demo/src/main/resources/turing/turing_award_1987.eml index 945c454505..2c4f82bbb0 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1987.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1987.eml @@ -1,42 +1,42 @@ -MIME-Version: 1.0 -From: John Cocke -Date: Mon, 16 Feb 1987 12:00:00 -0600 -Message-ID: -Subject: The Search for Performance in Scientific Processors -To: Alan Turing -Content-Type: multipart/alternative; boundary=047d7bfd079665fb2c04d85ad0bc - ---047d7bfd079665fb2c04d85ad0bc -Content-Type: text/plain; charset=UTF-8 - -I am honored and grateful to have been selected to join the ranks of ACM -Turing Award winners. I probably have spent too much of my life thinking -about computers, but I do not regret it a bit. I was fortunate to enter the -field of computing in its infancy and participate in its explosive growth. -The rapid evolution of the underlying technologies in the past 30 years has -not only provided an exciting environment, but has also presented a -constant stream of intellectual challenges to those of us trying to harness -this power and squeeze it to the last ounce. I hasten to say, especially to -the -younger members of the audience, there is no end in sight. As a matter of -fact, I believe the next thirty years will be even more exciting and rich -with challenges. - ---047d7bfd079665fb2c04d85ad0bc -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
I am honored and grateful to have been selected to jo= -in the ranks of ACM Turing Award winners. I probably have spent too much of= - my life thinking about computers, but I do not regret it a bit. I was fort= -unate to enter the field of computing in its infancy and participate in its= - explosive growth. The rapid evolution of the underlying technologies in th= -e past 30 years has not only provided an exciting environment, but has also= - presented a constant stream of intellectual challenges to those of us tryi= -ng to harness this power and squeeze it to the last ounce. I hasten to say,= - especially to the=C2=A0
-
younger members of the audience, there is no end in sight. As a matter= - of fact, I believe the next thirty years will be even more exciting and ri= -ch with challenges.=C2=A0
- ---047d7bfd079665fb2c04d85ad0bc-- +MIME-Version: 1.0 +From: John Cocke +Date: Mon, 16 Feb 1987 12:00:00 -0600 +Message-ID: +Subject: The Search for Performance in Scientific Processors +To: Alan Turing +Content-Type: multipart/alternative; boundary=047d7bfd079665fb2c04d85ad0bc + +--047d7bfd079665fb2c04d85ad0bc +Content-Type: text/plain; charset=UTF-8 + +I am honored and grateful to have been selected to join the ranks of ACM +Turing Award winners. I probably have spent too much of my life thinking +about computers, but I do not regret it a bit. I was fortunate to enter the +field of computing in its infancy and participate in its explosive growth. +The rapid evolution of the underlying technologies in the past 30 years has +not only provided an exciting environment, but has also presented a +constant stream of intellectual challenges to those of us trying to harness +this power and squeeze it to the last ounce. I hasten to say, especially to +the +younger members of the audience, there is no end in sight. As a matter of +fact, I believe the next thirty years will be even more exciting and rich +with challenges. + +--047d7bfd079665fb2c04d85ad0bc +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
I am honored and grateful to have been selected to jo= +in the ranks of ACM Turing Award winners. I probably have spent too much of= + my life thinking about computers, but I do not regret it a bit. I was fort= +unate to enter the field of computing in its infancy and participate in its= + explosive growth. The rapid evolution of the underlying technologies in th= +e past 30 years has not only provided an exciting environment, but has also= + presented a constant stream of intellectual challenges to those of us tryi= +ng to harness this power and squeeze it to the last ounce. I hasten to say,= + especially to the=C2=A0
+
younger members of the audience, there is no end in sight. As a matter= + of fact, I believe the next thirty years will be even more exciting and ri= +ch with challenges.=C2=A0
+ +--047d7bfd079665fb2c04d85ad0bc-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1991.eml b/backend/demo/src/main/resources/turing/turing_award_1991.eml index d068d60fa5..57e31d48d9 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1991.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1991.eml @@ -1,44 +1,44 @@ -MIME-Version: 1.0 -From: Robin Milner -Date: Mon, 18 Nov 1991 12:00:00 -0700 -Message-ID: -Subject: Elements of Interaction -To: Alan Turing -Content-Type: multipart/alternative; boundary=047d7b86e6de64aecb04d85affff - ---047d7b86e6de64aecb04d85affff -Content-Type: text/plain; charset=UTF-8 - -I am greatly honored to receive this award, bearing the name of Alan -Turing. Perhaps Turing would be pleased that it should go to someone -educated at his old college, King's College at Cambridge. While there in -1956 I wrote my first computer program; it was on the EDSAC. Of course -EDSAC made history. But I am ashamed to say it did not lure me into -computing, and I ignored computers for four years. In 1960 I thought that -computers might be more peaceful to handle than schoolchildren--I was then -a teacher--so I applied for a job at Ferranti in London, at the time of -Pegasus. I was asked at the interview whether I would like to devote my -life to computers. This daunting notion had never crossed my mind. Well, -here I am still, and I have had the lucky chance to grow alongside computer -science. - ---047d7b86e6de64aecb04d85affff -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
I am greatly honored to receive this award, bearing t= -he name of Alan Turing. Perhaps Turing would be pleased that it should go t= -o someone educated at his old college, King's College at Cambridge. Whi= -le there in 1956 I wrote my first computer program; it was on the EDSAC. Of= - course EDSAC made history. But I am ashamed to say it did not lure me into= - computing, and I ignored computers for four years. In 1960 I thought that = -computers might be more peaceful to handle than schoolchildren--I was then = -a teacher--so I applied for a job at Ferranti in London, at the time of=C2= -=A0
-
Pegasus. I was asked at the interview whether I would like to devote m= -y life to computers. This daunting notion had never crossed my mind. Well, = -here I am still, and I have had the lucky chance to grow alongside computer= - science.
-
- ---047d7b86e6de64aecb04d85affff-- +MIME-Version: 1.0 +From: Robin Milner +Date: Mon, 18 Nov 1991 12:00:00 -0700 +Message-ID: +Subject: Elements of Interaction +To: Alan Turing +Content-Type: multipart/alternative; boundary=047d7b86e6de64aecb04d85affff + +--047d7b86e6de64aecb04d85affff +Content-Type: text/plain; charset=UTF-8 + +I am greatly honored to receive this award, bearing the name of Alan +Turing. Perhaps Turing would be pleased that it should go to someone +educated at his old college, King's College at Cambridge. While there in +1956 I wrote my first computer program; it was on the EDSAC. Of course +EDSAC made history. But I am ashamed to say it did not lure me into +computing, and I ignored computers for four years. In 1960 I thought that +computers might be more peaceful to handle than schoolchildren--I was then +a teacher--so I applied for a job at Ferranti in London, at the time of +Pegasus. I was asked at the interview whether I would like to devote my +life to computers. This daunting notion had never crossed my mind. Well, +here I am still, and I have had the lucky chance to grow alongside computer +science. + +--047d7b86e6de64aecb04d85affff +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
I am greatly honored to receive this award, bearing t= +he name of Alan Turing. Perhaps Turing would be pleased that it should go t= +o someone educated at his old college, King's College at Cambridge. Whi= +le there in 1956 I wrote my first computer program; it was on the EDSAC. Of= + course EDSAC made history. But I am ashamed to say it did not lure me into= + computing, and I ignored computers for four years. In 1960 I thought that = +computers might be more peaceful to handle than schoolchildren--I was then = +a teacher--so I applied for a job at Ferranti in London, at the time of=C2= +=A0
+
Pegasus. I was asked at the interview whether I would like to devote m= +y life to computers. This daunting notion had never crossed my mind. Well, = +here I am still, and I have had the lucky chance to grow alongside computer= + science.
+
+ +--047d7b86e6de64aecb04d85affff-- diff --git a/backend/demo/src/main/resources/turing/turing_award_1996.eml b/backend/demo/src/main/resources/turing/turing_award_1996.eml index fb04a52d9f..2f8bb13a68 100644 --- a/backend/demo/src/main/resources/turing/turing_award_1996.eml +++ b/backend/demo/src/main/resources/turing/turing_award_1996.eml @@ -1,28 +1,28 @@ -MIME-Version: 1.0 -From: Amir Pnueli -Date: Thu, 15 Feb 1996 12:00:00 -0500 -Message-ID: -Subject: Verification Engineering: A Future Profession -To: Alan Turing -Content-Type: multipart/alternative; boundary=bcaec54fbb222acf6704d85aa523 - ---bcaec54fbb222acf6704d85aa523 -Content-Type: text/plain; charset=UTF-8 - -It is time that formal verification (of both software and hardware systems) -be demoted from an art practiced by the enlightened few to an activity -routinely and mundanely performed by a cadre of Verification Engineers (a -new profession), as a standard part of the system development process. - ---bcaec54fbb222acf6704d85aa523 -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: quoted-printable - -
It is time that formal verification (of both software= - and hardware systems) be demoted from an art practiced by the enlightened = -few to an activity routinely and mundanely performed by a cadre of Verifica= -tion Engineers (a new profession), as a standard part of the system develop= -ment process.
-
- ---bcaec54fbb222acf6704d85aa523-- +MIME-Version: 1.0 +From: Amir Pnueli +Date: Thu, 15 Feb 1996 12:00:00 -0500 +Message-ID: +Subject: Verification Engineering: A Future Profession +To: Alan Turing +Content-Type: multipart/alternative; boundary=bcaec54fbb222acf6704d85aa523 + +--bcaec54fbb222acf6704d85aa523 +Content-Type: text/plain; charset=UTF-8 + +It is time that formal verification (of both software and hardware systems) +be demoted from an art practiced by the enlightened few to an activity +routinely and mundanely performed by a cadre of Verification Engineers (a +new profession), as a standard part of the system development process. + +--bcaec54fbb222acf6704d85aa523 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable + +
It is time that formal verification (of both software= + and hardware systems) be demoted from an art practiced by the enlightened = +few to an activity routinely and mundanely performed by a cadre of Verifica= +tion Engineers (a new profession), as a standard part of the system develop= +ment process.
+
+ +--bcaec54fbb222acf6704d85aa523-- diff --git a/backend/jmap/src/test/resources/jmap_responses/blob/email/email_1.eml b/backend/jmap/src/test/resources/jmap_responses/blob/email/email_1.eml index 2847d4f199..803a3e1dd2 100644 --- a/backend/jmap/src/test/resources/jmap_responses/blob/email/email_1.eml +++ b/backend/jmap/src/test/resources/jmap_responses/blob/email/email_1.eml @@ -1,14 +1,14 @@ -From: alice@domain.example -To: bob@domain.example -Message-ID: -Date: Mon, 10 Feb 2020 10:20:30 +0100 -Subject: Hello there -Content-Type: text/plain; charset=UTF-8 -Mime-Version: 1.0 - -Hi Bob, - -this is a message from me to you. - -Cheers, -Alice +From: alice@domain.example +To: bob@domain.example +Message-ID: +Date: Mon, 10 Feb 2020 10:20:30 +0100 +Subject: Hello there +Content-Type: text/plain; charset=UTF-8 +Mime-Version: 1.0 + +Hi Bob, + +this is a message from me to you. + +Cheers, +Alice diff --git a/backend/jmap/src/test/resources/jmap_responses/blob/email/email_2.eml b/backend/jmap/src/test/resources/jmap_responses/blob/email/email_2.eml index 57faecf520..fcff100daa 100644 --- a/backend/jmap/src/test/resources/jmap_responses/blob/email/email_2.eml +++ b/backend/jmap/src/test/resources/jmap_responses/blob/email/email_2.eml @@ -1,16 +1,16 @@ -From: Bob -To: alice@domain.example -Message-ID: -In-Reply-To: -References: -Date: Mon, 10 Feb 2020 10:20:30 +0100 -Subject: Re: Hello there -Content-Type: text/plain; charset=UTF-8 -Mime-Version: 1.0 - -Hi Alice, - -I've received your message. - -Best, -Bob +From: Bob +To: alice@domain.example +Message-ID: +In-Reply-To: +References: +Date: Mon, 10 Feb 2020 10:20:30 +0100 +Subject: Re: Hello there +Content-Type: text/plain; charset=UTF-8 +Mime-Version: 1.0 + +Hi Alice, + +I've received your message. + +Best, +Bob diff --git a/backend/jmap/src/test/resources/jmap_responses/blob/email/email_3.eml b/backend/jmap/src/test/resources/jmap_responses/blob/email/email_3.eml index 46cd0c319c..6fa9b27fdd 100644 --- a/backend/jmap/src/test/resources/jmap_responses/blob/email/email_3.eml +++ b/backend/jmap/src/test/resources/jmap_responses/blob/email/email_3.eml @@ -1,9 +1,9 @@ -From: alice@domain.example -To: alice@domain.example -Message-ID: -Date: Mon, 10 Feb 2020 12:20:30 +0100 -Subject: Dummy -Content-Type: text/plain; charset=UTF-8 -Mime-Version: 1.0 - -- +From: alice@domain.example +To: alice@domain.example +Message-ID: +Date: Mon, 10 Feb 2020 12:20:30 +0100 +Subject: Dummy +Content-Type: text/plain; charset=UTF-8 +Mime-Version: 1.0 + +- diff --git a/docs/activity_diagram.graphml b/docs/activity_diagram.graphml index a2f1a42169..05a291a4f8 100644 --- a/docs/activity_diagram.graphml +++ b/docs/activity_diagram.graphml @@ -1,936 +1,936 @@ - - - - - - - - - - - - - - - - - - - - - - - Accounts - - - - - - - - - - - FolderList - - - - - - - - - - - MessageList - - - - - - - - - - - MessageView - - - - - - - - - - - AccountSettings - - - - - - - - - - - AccountSetupIncoming - - - - - - - - - - - AccountSetupOutgoing - - - - - - - - - - - Prefs - - - - - - - - - - - FontSizeSettings - - - - - - - - - - - AccountSetupOptions - - - - - - - - - - - AccountSetupNames - - - - - - - - - - - AccountSetupComposition - - - - - - - - - - - AccountSetupCheckSettings - - - - - - - - - - - AccountSetupBasics - - - - - - - - - - - AccountSetupAccountType - - - - - - - - - - - FolderSettings - - - - - - - - - - - ChooseAccount - - - - - - - - - - - ChooseFolder - - - - - - - - - - - ChooseIdentity - - - - - - - - - - - EditIdentity - - - - - - - - - - - LauncherShortcuts - - - - - - - - - - - ManageIdentities - - - - - - - - - - - MessageCompose - - - - - - - - - - - Other Apps / OS - - - - - - - - - - - Search - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + Accounts + + + + + + + + + + + FolderList + + + + + + + + + + + MessageList + + + + + + + + + + + MessageView + + + + + + + + + + + AccountSettings + + + + + + + + + + + AccountSetupIncoming + + + + + + + + + + + AccountSetupOutgoing + + + + + + + + + + + Prefs + + + + + + + + + + + FontSizeSettings + + + + + + + + + + + AccountSetupOptions + + + + + + + + + + + AccountSetupNames + + + + + + + + + + + AccountSetupComposition + + + + + + + + + + + AccountSetupCheckSettings + + + + + + + + + + + AccountSetupBasics + + + + + + + + + + + AccountSetupAccountType + + + + + + + + + + + FolderSettings + + + + + + + + + + + ChooseAccount + + + + + + + + + + + ChooseFolder + + + + + + + + + + + ChooseIdentity + + + + + + + + + + + EditIdentity + + + + + + + + + + + LauncherShortcuts + + + + + + + + + + + ManageIdentities + + + + + + + + + + + MessageCompose + + + + + + + + + + + Other Apps / OS + + + + + + + + + + + Search + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- GitLab From cafc78636797282525e6817685cfa6f2e0ff22eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 29 Aug 2023 19:10:37 +0200 Subject: [PATCH 05/94] Add error messages to allow better import debugging --- .../java/com/fsck/k9/preferences/Settings.java | 7 +++++++ .../fsck/k9/preferences/SettingsImporter.java | 16 ++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/app/core/src/main/java/com/fsck/k9/preferences/Settings.java b/app/core/src/main/java/com/fsck/k9/preferences/Settings.java index 1aa80b3a59..dcff73e46e 100644 --- a/app/core/src/main/java/com/fsck/k9/preferences/Settings.java +++ b/app/core/src/main/java/com/fsck/k9/preferences/Settings.java @@ -243,6 +243,13 @@ public class Settings { static class InvalidSettingValueException extends Exception { private static final long serialVersionUID = 1L; + + public InvalidSettingValueException() { + } + + public InvalidSettingValueException(String message) { + super(message); + } } /** diff --git a/app/core/src/main/java/com/fsck/k9/preferences/SettingsImporter.java b/app/core/src/main/java/com/fsck/k9/preferences/SettingsImporter.java index 3d9b261704..f7308902c6 100644 --- a/app/core/src/main/java/com/fsck/k9/preferences/SettingsImporter.java +++ b/app/core/src/main/java/com/fsck/k9/preferences/SettingsImporter.java @@ -253,8 +253,12 @@ public class SettingsImporter { erroneousAccounts.add(importResult.original); } } catch (InvalidSettingValueException e) { - Timber.e(e, "Encountered invalid setting while importing account \"%s\"", - account.name); + String reason = e.getMessage(); + if (TextUtils.isEmpty(reason)) { + reason = "Unknown"; + } + Timber.e(e, "Encountered invalid setting while importing account \"%s\", reason: \"%s\"", + account.name, reason); erroneousAccounts.add(new AccountDescription(account.name, account.uuid)); } catch (Exception e) { @@ -363,7 +367,7 @@ public class SettingsImporter { if (account.incoming == null) { // We don't import accounts without incoming server settings - throw new InvalidSettingValueException(); + throw new InvalidSettingValueException("Missing incoming server settings"); } // Write incoming server settings @@ -380,7 +384,7 @@ public class SettingsImporter { boolean authorizationNeeded = incoming.authenticationType == AuthType.XOAUTH2; if (account.outgoing == null) { - throw new InvalidSettingValueException(); + throw new InvalidSettingValueException("Missing outgoing server settings"); } String outgoingServerName = null; @@ -448,7 +452,7 @@ public class SettingsImporter { importIdentities(editor, contentVersion, uuid, account, overwrite, existingAccount, prefs); } else if (!mergeImportedAccount) { // Require accounts to at least have one identity - throw new InvalidSettingValueException(); + throw new InvalidSettingValueException("Missing identities, there should be at least one."); } // Write folder settings @@ -541,7 +545,7 @@ public class SettingsImporter { // Validate email address if (!IdentitySettingsDescriptions.isEmailAddressValid(identity.email)) { - throw new InvalidSettingValueException(); + throw new InvalidSettingValueException("Invalid email address: " + identity.email); } // Write email address -- GitLab From b2e9bf8fd0d5f63f050bb3cafd05749f6d13cb61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 30 Aug 2023 16:45:43 +0200 Subject: [PATCH 06/94] Fix eml line breaks to CRLF --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 6e15da8b7f..a00ea4be86 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ * text=auto *.bat eol=crlf +*.eml eol=crlf *.jar binary -- GitLab From 5fff204b9564bcd185cfc8ecd485e6142e299667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 30 Aug 2023 16:45:01 +0200 Subject: [PATCH 07/94] Move shared domain from setup to common module --- .../feature/preview/account/AccountCreator.kt | 2 +- app/k9mail/build.gradle.kts | 1 - .../com/fsck/k9/account/AccountCreator.kt | 3 +- feature/account/common/build.gradle.kts | 2 ++ .../account/common/AccountCommonModule.kt | 18 ++++++++++ .../data/InMemoryAccountStateRepository.kt} | 24 ++++++------- .../common/domain/AccountDomainContract.kt | 27 ++++++++++++++ .../account/common}/domain/entity/Account.kt | 2 +- .../common}/domain/entity/AccountOptions.kt | 2 +- .../common/domain/entity/AccountState.kt} | 5 ++- .../domain/entity/AuthorizationState.kt | 2 +- .../domain/entity/MailConnectionSecurity.kt | 3 ++ .../preview/PreviewAccountStateRepository.kt} | 18 +++++----- .../InMemoryAccountStateRepositoryTest.kt} | 36 +++++++++---------- feature/account/oauth/build.gradle.kts | 2 ++ .../account/oauth/data/AuthStateExtension.kt | 2 +- .../data/AuthorizationStateRepository.kt | 2 +- .../account/oauth/domain/DomainContract.kt | 2 +- .../domain/entity/AuthorizationResult.kt | 2 ++ .../oauth/domain/entity/OAuthResult.kt | 2 ++ .../domain/entity/ServerSettingsExtension.kt | 6 ++++ .../account/oauth/ui/AccountOAuthContract.kt | 2 +- .../account/oauth/ui/AccountOAuthViewModel.kt | 2 +- .../domain/usecase/FinishOAuthSignInTest.kt | 2 +- .../oauth/ui/AccountOAuthViewKtTest.kt | 2 +- .../oauth/ui/AccountOAuthViewModelTest.kt | 2 +- feature/account/setup/build.gradle.kts | 2 +- .../setup/AccountSetupExternalContract.kt | 2 +- .../account/setup/AccountSetupModule.kt | 25 +++++-------- .../account/setup/domain/DomainContract.kt | 22 +----------- .../setup/domain/entity/ConnectionSecurity.kt | 1 + .../domain/entity/MailConnectionSecurity.kt | 3 -- .../setup/domain/usecase/CreateAccount.kt | 4 +-- .../account/setup/ui/AccountSetupViewModel.kt | 20 +++++------ .../AccountAutoDiscoveryContract.kt | 2 +- .../AccountAutoDiscoveryScreen.kt | 6 ++-- .../AccountAutoDiscoveryStateMapper.kt | 6 ++-- .../AccountAutoDiscoveryViewModel.kt | 8 ++--- .../incoming/AccountIncomingConfigContract.kt | 2 +- .../incoming/AccountIncomingConfigScreen.kt | 8 ++--- .../AccountIncomingConfigStateMapper.kt | 4 +-- .../AccountIncomingConfigViewModel.kt | 14 ++++---- .../ui/options/AccountOptionsContract.kt | 2 +- .../setup/ui/options/AccountOptionsScreen.kt | 8 ++--- .../ui/options/AccountOptionsStateMapper.kt | 6 ++-- .../ui/options/AccountOptionsViewModel.kt | 14 ++++---- .../outgoing/AccountOutgoingConfigContract.kt | 2 +- .../outgoing/AccountOutgoingConfigScreen.kt | 8 ++--- .../AccountOutgoingConfigStateMapper.kt | 4 +-- .../AccountOutgoingConfigViewModel.kt | 14 ++++---- .../validation/AccountValidationContract.kt | 2 +- .../validation/AccountValidationMainScreen.kt | 10 +++--- .../ui/validation/AccountValidationScreen.kt | 2 +- .../AccountValidationStateMapper.kt | 4 +-- .../validation/AccountValidationViewModel.kt | 15 ++++---- .../account/setup/AccountSetupModuleKtTest.kt | 4 +-- .../setup/domain/AutoDiscoveryMapperKtTest.kt | 2 +- .../domain/entity/ConnectionSecurityTest.kt | 1 + .../setup/domain/usecase/CreateAccountTest.kt | 6 ++-- .../setup/ui/AccountSetupViewModelTest.kt | 30 ++++++++-------- .../AccountAutoDiscoveryStateMapperKtTest.kt | 10 +++--- .../AccountAutoDiscoveryViewModelTest.kt | 22 ++++++------ .../AccountIncomingConfigStateMapperKtTest.kt | 2 +- .../AccountIncomingConfigViewModelTest.kt | 36 +++++++++---------- .../AccountOptionsStateMapperKtTest.kt | 2 +- .../ui/options/AccountOptionsViewModelTest.kt | 8 ++--- .../AccountOutgoingConfigStateMapperKtTest.kt | 2 +- .../AccountOutgoingConfigViewModelTest.kt | 34 +++++++++--------- .../AccountValidationViewModelTest.kt | 18 +++++----- settings.gradle.kts | 10 ++++-- 70 files changed, 309 insertions(+), 271 deletions(-) create mode 100644 feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonModule.kt rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryAccountSetupStateRepository.kt => common/src/main/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepository.kt} (62%) create mode 100644 feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/AccountDomainContract.kt rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/entity/Account.kt (82%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/entity/AccountOptions.kt (80%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AccountSetupState.kt => common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountState.kt} (64%) rename feature/account/{oauth/src/main/kotlin/app/k9mail/feature/account/oauth => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/entity/AuthorizationState.kt (53%) create mode 100644 feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/MailConnectionSecurity.kt rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/preview/PreviewAccountSetupStateRepository.kt => common/src/main/kotlin/app/k9mail/feature/account/common/ui/preview/PreviewAccountStateRepository.kt} (67%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup/data/InMemoryAccountSetupStateRepositoryTest.kt => common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt} (81%) create mode 100644 feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/ServerSettingsExtension.kt delete mode 100644 feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/MailConnectionSecurity.kt diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/AccountCreator.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/AccountCreator.kt index 51d9f8f40b..5048b578c3 100644 --- a/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/AccountCreator.kt +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/AccountCreator.kt @@ -1,8 +1,8 @@ package app.k9mail.feature.preview.account +import app.k9mail.feature.account.common.domain.entity.Account import app.k9mail.feature.account.setup.AccountSetupExternalContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult -import app.k9mail.feature.account.setup.domain.entity.Account import java.util.UUID class AccountCreator : AccountSetupExternalContract.AccountCreator { diff --git a/app/k9mail/build.gradle.kts b/app/k9mail/build.gradle.kts index 530f4ead85..4e8618fd5b 100644 --- a/app/k9mail/build.gradle.kts +++ b/app/k9mail/build.gradle.kts @@ -20,7 +20,6 @@ dependencies { implementation(projects.core.featureflags) implementation(projects.feature.launcher) - // TODO remove account setup dependency implementation(projects.feature.account.setup) implementation(libs.androidx.appcompat) diff --git a/app/k9mail/src/main/java/com/fsck/k9/account/AccountCreator.kt b/app/k9mail/src/main/java/com/fsck/k9/account/AccountCreator.kt index 1602f8ca4b..80496250ae 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/account/AccountCreator.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/account/AccountCreator.kt @@ -2,9 +2,9 @@ package com.fsck.k9.account import android.content.Context import app.k9mail.core.common.mail.Protocols +import app.k9mail.feature.account.common.domain.entity.Account import app.k9mail.feature.account.setup.AccountSetupExternalContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult -import app.k9mail.feature.account.setup.domain.entity.Account import com.fsck.k9.Account.FolderMode import com.fsck.k9.Core import com.fsck.k9.Preferences @@ -19,6 +19,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +// TODO Move to feature/account/setup class AccountCreator( private val accountCreatorHelper: AccountCreatorHelper, private val localFoldersCreator: SpecialLocalFoldersCreator, diff --git a/feature/account/common/build.gradle.kts b/feature/account/common/build.gradle.kts index 743c8e4e00..aa32047961 100644 --- a/feature/account/common/build.gradle.kts +++ b/feature/account/common/build.gradle.kts @@ -11,5 +11,7 @@ dependencies { implementation(projects.core.ui.compose.designsystem) implementation(projects.core.common) + implementation(projects.mail.common) + testImplementation(projects.core.ui.compose.testing) } diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonModule.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonModule.kt new file mode 100644 index 0000000000..5ca9067c24 --- /dev/null +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonModule.kt @@ -0,0 +1,18 @@ +package app.k9mail.feature.account.common + +import app.k9mail.core.common.coreCommonModule +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.AccountDomainContract +import com.fsck.k9.mail.oauth.AuthStateStorage +import org.koin.core.module.Module +import org.koin.dsl.binds +import org.koin.dsl.module + +val featureAccountCommonModule: Module = module { + includes(coreCommonModule) + + // TODO: we need to provide one for setup and edit later on + single { + InMemoryAccountStateRepository() + }.binds(arrayOf(AccountDomainContract.AccountStateRepository::class, AuthStateStorage::class)) +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryAccountSetupStateRepository.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepository.kt similarity index 62% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryAccountSetupStateRepository.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepository.kt index 31d0d3e588..3a8c245bb6 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryAccountSetupStateRepository.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepository.kt @@ -1,22 +1,22 @@ -package app.k9mail.feature.account.setup.data +package app.k9mail.feature.account.common.data -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState -import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.AccountOptions -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.entity.AccountOptions +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.oauth.AuthStateStorage -class InMemoryAccountSetupStateRepository( - private var state: AccountSetupState = AccountSetupState(), -) : DomainContract.AccountSetupStateRepository, AuthStateStorage { +class InMemoryAccountStateRepository( + private var state: AccountState = AccountState(), +) : AccountDomainContract.AccountStateRepository, AuthStateStorage { - override fun getState(): AccountSetupState { + override fun getState(): AccountState { return state } - override fun save(accountSetupState: AccountSetupState) { - state = accountSetupState + override fun save(accountState: AccountState) { + state = accountState } override fun saveEmailAddress(emailAddress: String) { @@ -40,7 +40,7 @@ class InMemoryAccountSetupStateRepository( } override fun clear() { - state = AccountSetupState() + state = AccountState() } override fun getAuthorizationState(): String? { diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/AccountDomainContract.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/AccountDomainContract.kt new file mode 100644 index 0000000000..1fd0fe7f42 --- /dev/null +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/AccountDomainContract.kt @@ -0,0 +1,27 @@ +package app.k9mail.feature.account.common.domain + +import app.k9mail.feature.account.common.domain.entity.AccountOptions +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState +import com.fsck.k9.mail.ServerSettings + +interface AccountDomainContract { + + interface AccountStateRepository { + fun getState(): AccountState + + fun save(accountState: AccountState) + + fun saveEmailAddress(emailAddress: String) + + fun saveIncomingServerSettings(serverSettings: ServerSettings) + + fun saveOutgoingServerSettings(serverSettings: ServerSettings) + + fun saveAuthorizationState(authorizationState: AuthorizationState) + + fun saveOptions(options: AccountOptions) + + fun clear() + } +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/Account.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/Account.kt similarity index 82% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/Account.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/Account.kt index 0edc11e480..a5f0c7fe97 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/Account.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/Account.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity import com.fsck.k9.mail.ServerSettings diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AccountOptions.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountOptions.kt similarity index 80% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AccountOptions.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountOptions.kt index 403af527ac..21d8ffb0e6 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AccountOptions.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountOptions.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity data class AccountOptions( val accountName: String, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AccountSetupState.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountState.kt similarity index 64% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AccountSetupState.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountState.kt index db9cd1431e..b683854de3 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AccountSetupState.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountState.kt @@ -1,9 +1,8 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState import com.fsck.k9.mail.ServerSettings -data class AccountSetupState( +data class AccountState( val emailAddress: String? = null, val incomingServerSettings: ServerSettings? = null, val outgoingServerSettings: ServerSettings? = null, diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/AuthorizationState.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AuthorizationState.kt similarity index 53% rename from feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/AuthorizationState.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AuthorizationState.kt index 16fb9e649f..5d4e46fef5 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/AuthorizationState.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AuthorizationState.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.oauth.domain.entity +package app.k9mail.feature.account.common.domain.entity data class AuthorizationState( val state: String? = null, diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/MailConnectionSecurity.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/MailConnectionSecurity.kt new file mode 100644 index 0000000000..2f011726fa --- /dev/null +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/MailConnectionSecurity.kt @@ -0,0 +1,3 @@ +package app.k9mail.feature.account.common.domain.entity + +typealias MailConnectionSecurity = com.fsck.k9.mail.ConnectionSecurity diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/preview/PreviewAccountSetupStateRepository.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/preview/PreviewAccountStateRepository.kt similarity index 67% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/preview/PreviewAccountSetupStateRepository.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/preview/PreviewAccountStateRepository.kt index bc3aabb081..627f48e2e2 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/preview/PreviewAccountSetupStateRepository.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/preview/PreviewAccountStateRepository.kt @@ -1,15 +1,15 @@ -package app.k9mail.feature.account.setup.ui.preview +package app.k9mail.feature.account.common.ui.preview -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState -import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.AccountOptions -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState -import app.k9mail.feature.account.setup.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.entity.AccountOptions +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import com.fsck.k9.mail.AuthType import com.fsck.k9.mail.ServerSettings -class PreviewAccountSetupStateRepository : DomainContract.AccountSetupStateRepository { - override fun getState(): AccountSetupState = AccountSetupState( +class PreviewAccountStateRepository : AccountDomainContract.AccountStateRepository { + override fun getState(): AccountState = AccountState( emailAddress = "test@example.com", incomingServerSettings = ServerSettings( type = "imap", @@ -33,7 +33,7 @@ class PreviewAccountSetupStateRepository : DomainContract.AccountSetupStateRepos ), ) - override fun save(accountSetupState: AccountSetupState) = Unit + override fun save(accountState: AccountState) = Unit override fun saveEmailAddress(emailAddress: String) = Unit diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/data/InMemoryAccountSetupStateRepositoryTest.kt b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt similarity index 81% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/data/InMemoryAccountSetupStateRepositoryTest.kt rename to feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt index a234017f2b..3628d45ef0 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/data/InMemoryAccountSetupStateRepositoryTest.kt +++ b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.setup.data +package app.k9mail.feature.account.common.data -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState -import app.k9mail.feature.account.setup.domain.entity.AccountOptions -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.domain.entity.AccountOptions +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType @@ -10,16 +10,16 @@ import com.fsck.k9.mail.ConnectionSecurity import com.fsck.k9.mail.ServerSettings import org.junit.Test -class InMemoryAccountSetupStateRepositoryTest { +class InMemoryAccountStateRepositoryTest { @Test fun `should initialize with empty state`() { - val testSubject = InMemoryAccountSetupStateRepository() + val testSubject = InMemoryAccountStateRepository() val result = testSubject.getState() assertThat(result).isEqualTo( - AccountSetupState( + AccountState( emailAddress = null, incomingServerSettings = null, outgoingServerSettings = null, @@ -31,8 +31,8 @@ class InMemoryAccountSetupStateRepositoryTest { @Test fun `should save state`() { - val testSubject = InMemoryAccountSetupStateRepository( - AccountSetupState( + val testSubject = InMemoryAccountStateRepository( + AccountState( emailAddress = "emailAddress", incomingServerSettings = INCOMING_SERVER_SETTINGS, outgoingServerSettings = OUTGOING_SERVER_SETTINGS, @@ -40,7 +40,7 @@ class InMemoryAccountSetupStateRepositoryTest { options = OPTIONS, ), ) - val newState = AccountSetupState( + val newState = AccountState( emailAddress = "emailAddress2", incomingServerSettings = INCOMING_SERVER_SETTINGS.copy(host = "imap2.example.org"), outgoingServerSettings = OUTGOING_SERVER_SETTINGS.copy(host = "smtp2.example.org"), @@ -62,7 +62,7 @@ class InMemoryAccountSetupStateRepositoryTest { @Test fun `should save email address`() { - val testSubject = InMemoryAccountSetupStateRepository() + val testSubject = InMemoryAccountStateRepository() testSubject.saveEmailAddress("emailAddress") @@ -72,7 +72,7 @@ class InMemoryAccountSetupStateRepositoryTest { @Test fun `should save incoming server settings`() { - val testSubject = InMemoryAccountSetupStateRepository() + val testSubject = InMemoryAccountStateRepository() testSubject.saveIncomingServerSettings(INCOMING_SERVER_SETTINGS) @@ -82,7 +82,7 @@ class InMemoryAccountSetupStateRepositoryTest { @Test fun `should save outgoing server settings`() { - val testSubject = InMemoryAccountSetupStateRepository() + val testSubject = InMemoryAccountStateRepository() testSubject.saveOutgoingServerSettings(OUTGOING_SERVER_SETTINGS) @@ -92,7 +92,7 @@ class InMemoryAccountSetupStateRepositoryTest { @Test fun `should save authorization state`() { - val testSubject = InMemoryAccountSetupStateRepository() + val testSubject = InMemoryAccountStateRepository() testSubject.saveAuthorizationState(AuthorizationState("authorizationState")) @@ -102,7 +102,7 @@ class InMemoryAccountSetupStateRepositoryTest { @Test fun `should save options`() { - val testSubject = InMemoryAccountSetupStateRepository() + val testSubject = InMemoryAccountStateRepository() testSubject.saveOptions(OPTIONS) @@ -112,8 +112,8 @@ class InMemoryAccountSetupStateRepositoryTest { @Test fun `should clear state`() { - val testSubject = InMemoryAccountSetupStateRepository( - AccountSetupState( + val testSubject = InMemoryAccountStateRepository( + AccountState( emailAddress = "emailAddress", incomingServerSettings = INCOMING_SERVER_SETTINGS, outgoingServerSettings = OUTGOING_SERVER_SETTINGS, @@ -125,7 +125,7 @@ class InMemoryAccountSetupStateRepositoryTest { testSubject.clear() assertThat(testSubject.getState()).isEqualTo( - AccountSetupState( + AccountState( emailAddress = null, incomingServerSettings = null, outgoingServerSettings = null, diff --git a/feature/account/oauth/build.gradle.kts b/feature/account/oauth/build.gradle.kts index 4b73b20bb4..23b5c43aa5 100644 --- a/feature/account/oauth/build.gradle.kts +++ b/feature/account/oauth/build.gradle.kts @@ -19,7 +19,9 @@ android { dependencies { implementation(projects.core.ui.compose.designsystem) implementation(projects.core.common) + implementation(projects.mail.common) + implementation(projects.feature.account.common) implementation(libs.appauth) diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthStateExtension.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthStateExtension.kt index 33c9b8c37c..daba4ec578 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthStateExtension.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthStateExtension.kt @@ -1,6 +1,6 @@ package app.k9mail.feature.account.oauth.data -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import net.openid.appauth.AuthState import org.json.JSONException import timber.log.Timber diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationStateRepository.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationStateRepository.kt index 35ef90cc12..811ce67c7a 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationStateRepository.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationStateRepository.kt @@ -1,7 +1,7 @@ package app.k9mail.feature.account.oauth.data +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.oauth.domain.DomainContract -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState class AuthorizationStateRepository : DomainContract.AuthorizationStateRepository { override fun isAuthorized(authorizationState: AuthorizationState): Boolean { diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/DomainContract.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/DomainContract.kt index 157695b397..1afaaa28dc 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/DomainContract.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/DomainContract.kt @@ -2,9 +2,9 @@ package app.k9mail.feature.account.oauth.domain import android.content.Intent import app.k9mail.core.common.oauth.OAuthConfiguration +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.oauth.domain.entity.AuthorizationIntentResult import app.k9mail.feature.account.oauth.domain.entity.AuthorizationResult -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState import net.openid.appauth.AuthorizationException import net.openid.appauth.AuthorizationResponse diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/AuthorizationResult.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/AuthorizationResult.kt index 28cceab189..d8497d77b4 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/AuthorizationResult.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/AuthorizationResult.kt @@ -1,5 +1,7 @@ package app.k9mail.feature.account.oauth.domain.entity +import app.k9mail.feature.account.common.domain.entity.AuthorizationState + sealed interface AuthorizationResult { data class Success( diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/OAuthResult.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/OAuthResult.kt index 9bc7407b23..34e6094786 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/OAuthResult.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/OAuthResult.kt @@ -1,5 +1,7 @@ package app.k9mail.feature.account.oauth.domain.entity +import app.k9mail.feature.account.common.domain.entity.AuthorizationState + sealed interface OAuthResult { data class Success( val authorizationState: AuthorizationState, diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/ServerSettingsExtension.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/ServerSettingsExtension.kt new file mode 100644 index 0000000000..8d0e7f638d --- /dev/null +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/entity/ServerSettingsExtension.kt @@ -0,0 +1,6 @@ +package app.k9mail.feature.account.oauth.domain.entity + +import com.fsck.k9.mail.AuthType +import com.fsck.k9.mail.ServerSettings + +fun ServerSettings?.isOAuth() = this?.authenticationType == AuthType.XOAUTH2 diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthContract.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthContract.kt index 6b704f8c30..ca807756b2 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthContract.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthContract.kt @@ -2,8 +2,8 @@ package app.k9mail.feature.account.oauth.ui import android.content.Intent import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.common.ui.WizardNavigationBarState -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState interface AccountOAuthContract { diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModel.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModel.kt index 7204837a2e..e92e3eb7bd 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModel.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModel.kt @@ -4,10 +4,10 @@ import android.app.Activity import android.content.Intent import androidx.lifecycle.viewModelScope import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.oauth.domain.DomainContract.UseCase import app.k9mail.feature.account.oauth.domain.entity.AuthorizationIntentResult import app.k9mail.feature.account.oauth.domain.entity.AuthorizationResult -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract.Effect import app.k9mail.feature.account.oauth.ui.AccountOAuthContract.Error import app.k9mail.feature.account.oauth.ui.AccountOAuthContract.Event diff --git a/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/domain/usecase/FinishOAuthSignInTest.kt b/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/domain/usecase/FinishOAuthSignInTest.kt index 5a23e75170..e64e134026 100644 --- a/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/domain/usecase/FinishOAuthSignInTest.kt +++ b/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/domain/usecase/FinishOAuthSignInTest.kt @@ -1,9 +1,9 @@ package app.k9mail.feature.account.oauth.domain.usecase import android.content.Intent +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.oauth.domain.FakeAuthorizationRepository import app.k9mail.feature.account.oauth.domain.entity.AuthorizationResult -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest diff --git a/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewKtTest.kt b/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewKtTest.kt index 948dea3381..f393511c2a 100644 --- a/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewKtTest.kt +++ b/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewKtTest.kt @@ -3,7 +3,7 @@ package app.k9mail.feature.account.oauth.ui import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.setContent import app.k9mail.core.ui.compose.theme.ThunderbirdTheme -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.ui.AccountOAuthContract.Effect import app.k9mail.feature.account.oauth.ui.AccountOAuthContract.State diff --git a/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModelTest.kt b/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModelTest.kt index 5b02d150fb..a7769480b0 100644 --- a/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModelTest.kt +++ b/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModelTest.kt @@ -4,9 +4,9 @@ import android.app.Activity import android.content.Intent import app.cash.turbine.testIn import app.k9mail.core.ui.compose.testing.MainDispatcherRule +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.oauth.domain.entity.AuthorizationIntentResult import app.k9mail.feature.account.oauth.domain.entity.AuthorizationResult -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract.Effect import app.k9mail.feature.account.oauth.ui.AccountOAuthContract.Error import app.k9mail.feature.account.oauth.ui.AccountOAuthContract.Event diff --git a/feature/account/setup/build.gradle.kts b/feature/account/setup/build.gradle.kts index fbe8659767..5509595281 100644 --- a/feature/account/setup/build.gradle.kts +++ b/feature/account/setup/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { implementation(projects.mail.protocols.smtp) implementation(projects.feature.autodiscovery.service) - implementation(projects.feature.account.common) + api(projects.feature.account.common) implementation(projects.feature.account.oauth) testImplementation(projects.core.ui.compose.testing) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupExternalContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupExternalContract.kt index 768153f068..554f4180fe 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupExternalContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupExternalContract.kt @@ -1,6 +1,6 @@ package app.k9mail.feature.account.setup -import app.k9mail.feature.account.setup.domain.entity.Account +import app.k9mail.feature.account.common.domain.entity.Account interface AccountSetupExternalContract { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt index 0a1de6b030..e823a44711 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt @@ -2,9 +2,8 @@ package app.k9mail.feature.account.setup import app.k9mail.autodiscovery.api.AutoDiscoveryService import app.k9mail.autodiscovery.service.RealAutoDiscoveryService -import app.k9mail.core.common.coreCommonModule +import app.k9mail.feature.account.common.featureAccountCommonModule import app.k9mail.feature.account.oauth.featureAccountOAuthModule -import app.k9mail.feature.account.setup.data.InMemoryAccountSetupStateRepository import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository import app.k9mail.feature.account.setup.domain.DomainContract import app.k9mail.feature.account.setup.domain.usecase.AddServerCertificateException @@ -26,7 +25,6 @@ import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigValidat import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigViewModel import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorViewModel import app.k9mail.feature.account.setup.ui.validation.AccountValidationViewModel -import com.fsck.k9.mail.oauth.AuthStateStorage import com.fsck.k9.mail.store.imap.ImapServerSettingsValidator import com.fsck.k9.mail.store.pop3.Pop3ServerSettingsValidator import com.fsck.k9.mail.transport.smtp.SmtpServerSettingsValidator @@ -34,11 +32,10 @@ import okhttp3.OkHttpClient import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.core.module.Module import org.koin.core.qualifier.named -import org.koin.dsl.binds import org.koin.dsl.module val featureAccountSetupModule: Module = module { - includes(coreCommonModule, featureAccountOAuthModule) + includes(featureAccountCommonModule, featureAccountOAuthModule) single { OkHttpClient() @@ -57,10 +54,6 @@ val featureAccountSetupModule: Module = module { ) } - single { - InMemoryAccountSetupStateRepository() - }.binds(arrayOf(DomainContract.AccountSetupStateRepository::class, AuthStateStorage::class)) - single { InMemoryCertificateErrorRepository() } factory { @@ -101,27 +94,27 @@ val featureAccountSetupModule: Module = module { viewModel { AccountSetupViewModel( createAccount = get(), - accountSetupStateRepository = get(), + accountStateRepository = get(), ) } viewModel { AccountAutoDiscoveryViewModel( validator = get(), getAutoDiscovery = get(), - accountSetupStateRepository = get(), + accountStateRepository = get(), oAuthViewModel = get(), ) } viewModel { AccountIncomingConfigViewModel( validator = get(), - accountSetupStateRepository = get(), + accountStateRepository = get(), ) } viewModel(named(NAME_INCOMING_VALIDATION)) { AccountValidationViewModel( validateServerSettings = get(), - accountSetupStateRepository = get(), + accountStateRepository = get(), authorizationStateRepository = get(), certificateErrorRepository = get(), oAuthViewModel = get(), @@ -131,13 +124,13 @@ val featureAccountSetupModule: Module = module { viewModel { AccountOutgoingConfigViewModel( validator = get(), - accountSetupStateRepository = get(), + accountStateRepository = get(), ) } viewModel(named(NAME_OUTGOING_VALIDATION)) { AccountValidationViewModel( validateServerSettings = get(), - accountSetupStateRepository = get(), + accountStateRepository = get(), authorizationStateRepository = get(), certificateErrorRepository = get(), oAuthViewModel = get(), @@ -147,7 +140,7 @@ val featureAccountSetupModule: Module = module { viewModel { AccountOptionsViewModel( validator = get(), - accountSetupStateRepository = get(), + accountStateRepository = get(), ) } viewModel { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt index e795f149b7..0a77856e38 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt @@ -2,9 +2,7 @@ package app.k9mail.feature.account.setup.domain import app.k9mail.autodiscovery.api.AutoDiscoveryResult import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState -import app.k9mail.feature.account.setup.domain.entity.AccountOptions -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.domain.entity.AccountOptions import app.k9mail.feature.account.setup.domain.entity.CertificateError import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.server.ServerSettingsValidationResult @@ -12,24 +10,6 @@ import java.security.cert.X509Certificate interface DomainContract { - interface AccountSetupStateRepository { - fun getState(): AccountSetupState - - fun save(accountSetupState: AccountSetupState) - - fun saveEmailAddress(emailAddress: String) - - fun saveIncomingServerSettings(serverSettings: ServerSettings) - - fun saveOutgoingServerSettings(serverSettings: ServerSettings) - - fun saveAuthorizationState(authorizationState: AuthorizationState) - - fun saveOptions(options: AccountOptions) - - fun clear() - } - interface CertificateErrorRepository { fun getCertificateError(): CertificateError? diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurity.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurity.kt index beb5f18836..d9a44316bd 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurity.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurity.kt @@ -1,5 +1,6 @@ package app.k9mail.feature.account.setup.domain.entity +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity.None import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity.StartTLS import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity.TLS diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/MailConnectionSecurity.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/MailConnectionSecurity.kt deleted file mode 100644 index 7e4a9efacf..0000000000 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/MailConnectionSecurity.kt +++ /dev/null @@ -1,3 +0,0 @@ -package app.k9mail.feature.account.setup.domain.entity - -internal typealias MailConnectionSecurity = com.fsck.k9.mail.ConnectionSecurity diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccount.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccount.kt index bbcc1975a6..a9a199278f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccount.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccount.kt @@ -1,10 +1,10 @@ package app.k9mail.feature.account.setup.domain.usecase +import app.k9mail.feature.account.common.domain.entity.Account +import app.k9mail.feature.account.common.domain.entity.AccountOptions import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult import app.k9mail.feature.account.setup.domain.DomainContract.UseCase -import app.k9mail.feature.account.setup.domain.entity.Account -import app.k9mail.feature.account.setup.domain.entity.AccountOptions import com.fsck.k9.mail.ServerSettings class CreateAccount( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModel.kt index 8e3d36466b..2e3a90f120 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModel.kt @@ -2,8 +2,8 @@ package app.k9mail.feature.account.setup.ui import androidx.lifecycle.viewModelScope import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.setup.domain.DomainContract.UseCase import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect import app.k9mail.feature.account.setup.ui.AccountSetupContract.Event @@ -14,7 +14,7 @@ import kotlinx.coroutines.launch @Suppress("LongParameterList") class AccountSetupViewModel( private val createAccount: UseCase.CreateAccount, - private val accountSetupStateRepository: DomainContract.AccountSetupStateRepository, + private val accountStateRepository: AccountDomainContract.AccountStateRepository, initialState: State = State(), ) : BaseViewModel(initialState), AccountSetupContract.ViewModel { @@ -104,7 +104,7 @@ class AccountSetupViewModel( private fun changeToSetupStep(setupStep: SetupStep) { if (setupStep == SetupStep.AUTO_CONFIG) { - accountSetupStateRepository.saveAuthorizationState(AuthorizationState(null)) + accountStateRepository.saveAuthorizationState(AuthorizationState(null)) } updateState { @@ -115,15 +115,15 @@ class AccountSetupViewModel( } private fun onFinish() { - val accountSetupState = accountSetupStateRepository.getState() + val accountState = accountStateRepository.getState() viewModelScope.launch { val result = createAccount.execute( - emailAddress = accountSetupState.emailAddress ?: "", - incomingServerSettings = accountSetupState.incomingServerSettings!!, - outgoingServerSettings = accountSetupState.outgoingServerSettings!!, - authorizationState = accountSetupState.authorizationState?.state, - options = accountSetupState.options!!, + emailAddress = accountState.emailAddress ?: "", + incomingServerSettings = accountState.incomingServerSettings!!, + outgoingServerSettings = accountState.outgoingServerSettings!!, + authorizationState = accountState.authorizationState?.state, + options = accountState.options!!, ) navigateNext(result) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt index 346b34d537..f8ae81ddc8 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt @@ -3,7 +3,7 @@ package app.k9mail.feature.account.setup.ui.autodiscovery import app.k9mail.autodiscovery.api.AutoDiscoveryResult import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel -import app.k9mail.feature.account.oauth.domain.entity.AuthorizationState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.setup.domain.input.BooleanInputField diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryScreen.kt index b533c38788..174e00ba75 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryScreen.kt @@ -13,12 +13,12 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.ui.AppTitleTopHeader import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.WizardNavigationBarState +import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.oauth.ui.preview.PreviewAccountOAuthViewModel import app.k9mail.feature.account.setup.R import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.Effect import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.Event import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.ViewModel -import app.k9mail.feature.account.setup.ui.preview.PreviewAccountSetupStateRepository @Composable internal fun AccountAutoDiscoveryScreen( @@ -74,7 +74,7 @@ internal fun AccountAutoDiscoveryScreenK9Preview() { viewModel = AccountAutoDiscoveryViewModel( validator = AccountAutoDiscoveryValidator(), getAutoDiscovery = { AutoDiscoveryResult.NoUsableSettingsFound }, - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), ), ) @@ -91,7 +91,7 @@ internal fun AccountAutoDiscoveryScreenThunderbirdPreview() { viewModel = AccountAutoDiscoveryViewModel( validator = AccountAutoDiscoveryValidator(), getAutoDiscovery = { AutoDiscoveryResult.NoUsableSettingsFound }, - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), ), ) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt index 27ad77184e..ef50aba7a3 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.setup.ui.autodiscovery import app.k9mail.autodiscovery.api.ImapServerSettings import app.k9mail.autodiscovery.api.SmtpServerSettings -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toIncomingProtocolType @@ -13,8 +13,8 @@ import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContrac import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract -internal fun AccountAutoDiscoveryContract.State.toAccountSetupState(): AccountSetupState { - return AccountSetupState( +internal fun AccountAutoDiscoveryContract.State.toAccountState(): AccountState { + return AccountState( emailAddress = emailAddress.value, incomingServerSettings = autoDiscoverySettings?.incomingServerSettings?.toServerSettings(password.value), outgoingServerSettings = autoDiscoverySettings?.outgoingServerSettings?.toServerSettings(password.value), diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt index fec25ba15c..43d76616d8 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt @@ -5,9 +5,9 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryResult import app.k9mail.autodiscovery.api.ImapServerSettings import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.ui.AccountOAuthContract -import app.k9mail.feature.account.setup.domain.DomainContract import app.k9mail.feature.account.setup.domain.DomainContract.UseCase import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType import app.k9mail.feature.account.setup.domain.input.StringInputField @@ -24,7 +24,7 @@ internal class AccountAutoDiscoveryViewModel( initialState: State = State(), private val validator: Validator, private val getAutoDiscovery: UseCase.GetAutoDiscovery, - private val accountSetupStateRepository: DomainContract.AccountSetupStateRepository, + private val accountStateRepository: AccountDomainContract.AccountStateRepository, override val oAuthViewModel: AccountOAuthContract.ViewModel, ) : BaseViewModel(initialState), AccountAutoDiscoveryContract.ViewModel { @@ -51,7 +51,7 @@ internal class AccountAutoDiscoveryViewModel( } private fun changeEmailAddress(emailAddress: String) { - accountSetupStateRepository.clear() + accountStateRepository.clear() updateState { State( emailAddress = StringInputField(value = emailAddress), @@ -250,7 +250,7 @@ internal class AccountAutoDiscoveryViewModel( private fun navigateBack() = emitEffect(Effect.NavigateBack) private fun navigateNext(isAutomaticConfig: Boolean) { - accountSetupStateRepository.save(state.value.toAccountSetupState()) + accountStateRepository.save(state.value.toAccountState()) emitEffect(Effect.NavigateNext(isAutomaticConfig)) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt index 403671bb96..304bcd5ad7 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt @@ -44,7 +44,7 @@ interface AccountIncomingConfigContract { data class ImapUseCompressionChanged(val useCompression: Boolean) : Event data class ImapSendClientIdChanged(val sendClientId: Boolean) : Event - object LoadAccountSetupState : Event + object LoadAccountState : Event object OnNextClicked : Event object OnBackClicked : Event diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt index 236acee88b..7d0d5de668 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt @@ -11,12 +11,12 @@ import app.k9mail.core.ui.compose.designsystem.template.Scaffold import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.ui.WizardNavigationBar +import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.setup.R import app.k9mail.feature.account.setup.ui.common.AccountSetupTopAppBar import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.ViewModel -import app.k9mail.feature.account.setup.ui.preview.PreviewAccountSetupStateRepository @Composable internal fun AccountIncomingConfigScreen( @@ -33,7 +33,7 @@ internal fun AccountIncomingConfigScreen( } LaunchedEffect(key1 = Unit) { - dispatch(Event.LoadAccountSetupState) + dispatch(Event.LoadAccountState) } BackHandler { @@ -73,7 +73,7 @@ internal fun AccountIncomingConfigScreenK9Preview() { onBack = {}, viewModel = AccountIncomingConfigViewModel( validator = AccountIncomingConfigValidator(), - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), ), ) } @@ -88,7 +88,7 @@ internal fun AccountIncomingConfigScreenThunderbirdPreview() { onBack = {}, viewModel = AccountIncomingConfigViewModel( validator = AccountIncomingConfigValidator(), - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), ), ) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt index cfba40c121..df41531f82 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt @@ -1,6 +1,6 @@ package app.k9mail.feature.account.setup.ui.incoming -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType import app.k9mail.feature.account.setup.domain.entity.toAuthType import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType @@ -13,7 +13,7 @@ import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.store.imap.ImapStoreSettings -internal fun AccountSetupState.toIncomingConfigState(): State { +internal fun AccountState.toIncomingConfigState(): State { val incomingServerSettings = incomingServerSettings return if (incomingServerSettings == null) { State( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt index bb8e096258..e0ee4960dd 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.setup.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType import app.k9mail.feature.account.setup.domain.entity.toDefaultPort @@ -14,17 +14,17 @@ import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContrac internal class AccountIncomingConfigViewModel( private val validator: Validator, - private val accountSetupStateRepository: DomainContract.AccountSetupStateRepository, + private val accountStateRepository: AccountDomainContract.AccountStateRepository, initialState: State? = null, ) : BaseViewModel( - initialState = initialState ?: accountSetupStateRepository.getState().toIncomingConfigState(), + initialState = initialState ?: accountStateRepository.getState().toIncomingConfigState(), ), ViewModel { @Suppress("CyclomaticComplexMethod") override fun event(event: Event) { when (event) { - Event.LoadAccountSetupState -> loadAccountSetupState() + Event.LoadAccountState -> loadAccountState() is Event.ProtocolTypeChanged -> updateProtocolType(event.protocolType) is Event.ServerChanged -> updateState { it.copy(server = it.server.updateValue(event.server)) } @@ -53,9 +53,9 @@ internal class AccountIncomingConfigViewModel( } } - private fun loadAccountSetupState() { + private fun loadAccountState() { updateState { - accountSetupStateRepository.getState().toIncomingConfigState() + accountStateRepository.getState().toIncomingConfigState() } } @@ -117,7 +117,7 @@ internal class AccountIncomingConfigViewModel( } if (!hasError) { - accountSetupStateRepository.saveIncomingServerSettings(state.value.toServerSettings()) + accountStateRepository.saveIncomingServerSettings(state.value.toServerSettings()) navigateNext() } } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsContract.kt index 4472a6ed53..6717c65795 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsContract.kt @@ -27,7 +27,7 @@ interface AccountOptionsContract { data class OnMessageDisplayCountChanged(val messageDisplayCount: EmailDisplayCount) : Event data class OnShowNotificationChanged(val showNotification: Boolean) : Event - object LoadAccountSetupState : Event + object LoadAccountState : Event object OnNextClicked : Event object OnBackClicked : Event diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt index 0af78ec625..6c89bcb20d 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt @@ -11,12 +11,12 @@ import app.k9mail.core.ui.compose.designsystem.template.Scaffold import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.ui.WizardNavigationBar +import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.setup.R.string import app.k9mail.feature.account.setup.ui.common.AccountSetupTopAppBar import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.Effect import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.Event import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.ViewModel -import app.k9mail.feature.account.setup.ui.preview.PreviewAccountSetupStateRepository @Composable internal fun AccountOptionsScreen( @@ -33,7 +33,7 @@ internal fun AccountOptionsScreen( } LaunchedEffect(key1 = Unit) { - dispatch(Event.LoadAccountSetupState) + dispatch(Event.LoadAccountState) } BackHandler { @@ -73,7 +73,7 @@ internal fun AccountOptionsScreenK9Preview() { onBack = {}, viewModel = AccountOptionsViewModel( validator = AccountOptionsValidator(), - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), ), ) } @@ -88,7 +88,7 @@ internal fun AccountOptionsScreenThunderbirdPreview() { onBack = {}, viewModel = AccountOptionsViewModel( validator = AccountOptionsValidator(), - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), ), ) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapper.kt index 58d0c88b20..f9aca0adaf 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapper.kt @@ -1,13 +1,13 @@ package app.k9mail.feature.account.setup.ui.options -import app.k9mail.feature.account.setup.domain.entity.AccountOptions -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.domain.entity.AccountOptions +import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.setup.domain.entity.EmailCheckFrequency import app.k9mail.feature.account.setup.domain.entity.EmailDisplayCount import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.State -internal fun AccountSetupState.toAccountOptionsState(): State { +internal fun AccountState.toAccountOptionsState(): State { val options = options return if (options == null) { State( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModel.kt index 02e2901c54..9f2b4196cb 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModel.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.setup.ui.options import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.Effect import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.Event import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.State @@ -11,16 +11,16 @@ import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.ViewMo internal class AccountOptionsViewModel( private val validator: Validator, - private val accountSetupStateRepository: DomainContract.AccountSetupStateRepository, + private val accountStateRepository: AccountDomainContract.AccountStateRepository, initialState: State? = null, ) : BaseViewModel( - initialState = initialState ?: accountSetupStateRepository.getState().toAccountOptionsState(), + initialState = initialState ?: accountStateRepository.getState().toAccountOptionsState(), ), ViewModel { override fun event(event: Event) { when (event) { - Event.LoadAccountSetupState -> loadAccountSetupState() + Event.LoadAccountState -> loadAccountState() is Event.OnAccountNameChanged -> updateState { state -> state.copy( @@ -63,9 +63,9 @@ internal class AccountOptionsViewModel( } } - private fun loadAccountSetupState() { + private fun loadAccountState() { updateState { - accountSetupStateRepository.getState().toAccountOptionsState() + accountStateRepository.getState().toAccountOptionsState() } } @@ -89,7 +89,7 @@ internal class AccountOptionsViewModel( } if (!hasError) { - accountSetupStateRepository.saveOptions(state.value.toAccountOptions()) + accountStateRepository.saveOptions(state.value.toAccountOptions()) navigateNext() } } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt index daf9e3e4fa..7373a80c2c 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt @@ -31,7 +31,7 @@ interface AccountOutgoingConfigContract { data class PasswordChanged(val password: String) : Event data class ClientCertificateChanged(val clientCertificateAlias: String?) : Event - object LoadAccountSetupState : Event + object LoadAccountState : Event object OnNextClicked : Event object OnBackClicked : Event diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt index e491c9916a..279a79e9d4 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt @@ -11,12 +11,12 @@ import app.k9mail.core.ui.compose.designsystem.template.Scaffold import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.ui.WizardNavigationBar +import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.setup.R import app.k9mail.feature.account.setup.ui.common.AccountSetupTopAppBar import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.ViewModel -import app.k9mail.feature.account.setup.ui.preview.PreviewAccountSetupStateRepository @Composable internal fun AccountOutgoingConfigScreen( @@ -33,7 +33,7 @@ internal fun AccountOutgoingConfigScreen( } LaunchedEffect(key1 = Unit) { - dispatch(Event.LoadAccountSetupState) + dispatch(Event.LoadAccountState) } BackHandler { @@ -73,7 +73,7 @@ internal fun AccountOutgoingConfigScreenK9Preview() { onBack = {}, viewModel = AccountOutgoingConfigViewModel( validator = AccountOutgoingConfigValidator(), - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), ), ) } @@ -88,7 +88,7 @@ internal fun AccountOutgoingConfigScreenThunderbirdPreview() { onBack = {}, viewModel = AccountOutgoingConfigViewModel( validator = AccountOutgoingConfigValidator(), - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), ), ) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt index ca636f95e2..e388cdcedf 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt @@ -1,6 +1,6 @@ package app.k9mail.feature.account.setup.ui.outgoing -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.setup.domain.entity.toAuthType import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity @@ -11,7 +11,7 @@ import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContrac import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract import com.fsck.k9.mail.ServerSettings -internal fun AccountSetupState.toOutgoingConfigState(): State { +internal fun AccountState.toOutgoingConfigState(): State { val outgoingServerSettings = outgoingServerSettings return if (outgoingServerSettings == null) { State( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt index 73b761e1b8..9e10d344b7 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.setup.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect @@ -13,16 +13,16 @@ import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContrac internal class AccountOutgoingConfigViewModel( private val validator: Validator, - private val accountSetupStateRepository: DomainContract.AccountSetupStateRepository, + private val accountStateRepository: AccountDomainContract.AccountStateRepository, initialState: State? = State(), ) : BaseViewModel( - initialState = initialState ?: accountSetupStateRepository.getState().toOutgoingConfigState(), + initialState = initialState ?: accountStateRepository.getState().toOutgoingConfigState(), ), ViewModel { override fun event(event: Event) { when (event) { - Event.LoadAccountSetupState -> loadAccountSetupState() + Event.LoadAccountState -> loadAccountState() is Event.ServerChanged -> updateState { it.copy(server = it.server.updateValue(event.server)) } is Event.SecurityChanged -> updateSecurity(event.security) @@ -39,9 +39,9 @@ internal class AccountOutgoingConfigViewModel( } } - private fun loadAccountSetupState() { + private fun loadAccountState() { updateState { - accountSetupStateRepository.getState().toOutgoingConfigState() + accountStateRepository.getState().toOutgoingConfigState() } } @@ -81,7 +81,7 @@ internal class AccountOutgoingConfigViewModel( } if (!hasError) { - accountSetupStateRepository.saveOutgoingServerSettings(state.value.toServerSettings()) + accountStateRepository.saveOutgoingServerSettings(state.value.toServerSettings()) navigateNext() } } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContract.kt index a7edfee0dc..47e382bb19 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContract.kt @@ -24,7 +24,7 @@ interface AccountValidationContract { ) sealed interface Event { - object LoadAccountSetupStateAndValidate : Event + object LoadAccountStateAndValidate : Event data class OnOAuthResult(val result: OAuthResult) : Event diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt index 16709f10b4..b497174085 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt @@ -11,10 +11,10 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.ui.AppTitleTopHeader import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.WizardNavigationBarState +import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.oauth.ui.preview.PreviewAccountOAuthViewModel import app.k9mail.feature.account.setup.R import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository -import app.k9mail.feature.account.setup.ui.preview.PreviewAccountSetupStateRepository import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.ViewModel import com.fsck.k9.mail.server.ServerSettingsValidationResult @@ -63,7 +63,7 @@ internal fun AccountIncomingValidationScreenK9Preview() { validateServerSettings = { ServerSettingsValidationResult.Success }, - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, certificateErrorRepository = InMemoryCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), @@ -82,7 +82,7 @@ internal fun AccountIncomingValidationScreenThunderbirdPreview() { validateServerSettings = { ServerSettingsValidationResult.Success }, - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, certificateErrorRepository = InMemoryCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), @@ -101,7 +101,7 @@ internal fun AccountOutgoingValidationScreenK9Preview() { validateServerSettings = { ServerSettingsValidationResult.Success }, - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, certificateErrorRepository = InMemoryCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), @@ -120,7 +120,7 @@ internal fun AccountOutgoingValidationScreenThunderbirdPreview() { validateServerSettings = { ServerSettingsValidationResult.Success }, - accountSetupStateRepository = PreviewAccountSetupStateRepository(), + accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, certificateErrorRepository = InMemoryCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt index 0b7de7ac32..5cdd6d5d40 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt @@ -25,7 +25,7 @@ internal fun AccountValidationScreen( } LaunchedEffect(key1 = Unit) { - dispatch(Event.LoadAccountSetupStateAndValidate) + dispatch(Event.LoadAccountStateAndValidate) } BackHandler { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateMapper.kt index 3087c7f015..8a33ed30b4 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateMapper.kt @@ -1,8 +1,8 @@ package app.k9mail.feature.account.setup.ui.validation -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.domain.entity.AccountState -internal fun AccountSetupState.toValidationState(isIncomingValidation: Boolean): AccountValidationContract.State { +internal fun AccountState.toValidationState(isIncomingValidation: Boolean): AccountValidationContract.State { return AccountValidationContract.State( emailAddress = emailAddress, serverSettings = if (isIncomingValidation) incomingServerSettings else outgoingServerSettings, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt index f628ff65c2..59895e0663 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt @@ -2,6 +2,7 @@ package app.k9mail.feature.account.setup.ui.validation import androidx.lifecycle.viewModelScope import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.setup.domain.DomainContract @@ -22,20 +23,20 @@ private const val CONTINUE_NEXT_DELAY = 2000L @Suppress("TooManyFunctions") internal class AccountValidationViewModel( private val validateServerSettings: DomainContract.UseCase.ValidateServerSettings, - private val accountSetupStateRepository: DomainContract.AccountSetupStateRepository, + private val accountStateRepository: AccountDomainContract.AccountStateRepository, private val authorizationStateRepository: OAuthDomainContract.AuthorizationStateRepository, private val certificateErrorRepository: DomainContract.CertificateErrorRepository, override val oAuthViewModel: AccountOAuthContract.ViewModel, override val isIncomingValidation: Boolean = true, initialState: State? = null, ) : BaseViewModel( - initialState = initialState ?: accountSetupStateRepository.getState().toValidationState(isIncomingValidation), + initialState = initialState ?: accountStateRepository.getState().toValidationState(isIncomingValidation), ), AccountValidationContract.ViewModel { override fun event(event: Event) { when (event) { - Event.LoadAccountSetupStateAndValidate -> loadAccountSetupStateAndValidate() + Event.LoadAccountStateAndValidate -> loadAccountStateAndValidate() is Event.OnOAuthResult -> onOAuthResult(event.result) Event.ValidateServerSettings -> onValidateConfig() Event.OnNextClicked -> navigateNext() @@ -45,9 +46,9 @@ internal class AccountValidationViewModel( } } - private fun loadAccountSetupStateAndValidate() { + private fun loadAccountStateAndValidate() { updateState { - accountSetupStateRepository.getState().toValidationState(isIncomingValidation) + accountStateRepository.getState().toValidationState(isIncomingValidation) } onValidateConfig() } @@ -63,7 +64,7 @@ internal class AccountValidationViewModel( } private fun checkOAuthState() { - val authorizationState = accountSetupStateRepository.getState().authorizationState + val authorizationState = accountStateRepository.getState().authorizationState if (authorizationState != null) { if (authorizationStateRepository.isAuthorized(authorizationState)) { validateServerSettings() @@ -100,7 +101,7 @@ internal class AccountValidationViewModel( private fun onOAuthResult(result: OAuthResult) { if (result is OAuthResult.Success) { - accountSetupStateRepository.saveAuthorizationState(result.authorizationState) + accountStateRepository.saveAuthorizationState(result.authorizationState) updateState { it.copy( needsAuthorization = false, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index c5552ff0f1..05d3546bdc 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -2,10 +2,10 @@ package app.k9mail.feature.account.setup import android.content.Context import app.k9mail.core.common.oauth.OAuthConfigurationFactory +import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState import app.k9mail.feature.account.setup.ui.AccountSetupContract import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract @@ -68,7 +68,7 @@ class AccountSetupModuleKtTest : KoinTest { AccountIncomingConfigContract.State::class, AccountOutgoingConfigContract.State::class, AccountOptionsContract.State::class, - AccountSetupState::class, + AccountState::class, CertificateErrorContract.State::class, AuthStateStorage::class, Context::class, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/AutoDiscoveryMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/AutoDiscoveryMapperKtTest.kt index 4a9f0cecfe..d254912ae2 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/AutoDiscoveryMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/AutoDiscoveryMapperKtTest.kt @@ -8,7 +8,7 @@ import app.k9mail.autodiscovery.api.OutgoingServerSettings import app.k9mail.autodiscovery.api.SmtpServerSettings import app.k9mail.core.common.net.Hostname import app.k9mail.core.common.net.Port -import app.k9mail.feature.account.setup.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurityTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurityTest.kt index 0f74a657ca..64de5d12fe 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurityTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurityTest.kt @@ -1,5 +1,6 @@ package app.k9mail.feature.account.setup.domain.entity +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccountTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccountTest.kt index f6a53976b7..81249044e9 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccountTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccountTest.kt @@ -1,9 +1,9 @@ package app.k9mail.feature.account.setup.domain.usecase +import app.k9mail.feature.account.common.domain.entity.Account +import app.k9mail.feature.account.common.domain.entity.AccountOptions +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult -import app.k9mail.feature.account.setup.domain.entity.Account -import app.k9mail.feature.account.setup.domain.entity.AccountOptions -import app.k9mail.feature.account.setup.domain.entity.MailConnectionSecurity import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModelTest.kt index c9937c5fef..3d07a7f9e9 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModelTest.kt @@ -3,10 +3,10 @@ package app.k9mail.feature.account.setup.ui import app.k9mail.core.ui.compose.testing.MainDispatcherRule import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck -import app.k9mail.feature.account.setup.data.InMemoryAccountSetupStateRepository -import app.k9mail.feature.account.setup.domain.entity.AccountOptions -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState -import app.k9mail.feature.account.setup.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.entity.AccountOptions +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep import app.k9mail.feature.account.setup.ui.AccountSetupContract.State @@ -33,7 +33,7 @@ class AccountSetupViewModelTest { var createAccountOutgoingServerSettings: ServerSettings? = null var createAccountAuthorizationState: String? = null var createAccountOptions: AccountOptions? = null - val accountSetupStateRepository = InMemoryAccountSetupStateRepository() + val accountStateRepository = InMemoryAccountStateRepository() val viewModel = AccountSetupViewModel( createAccount = { emailAddress, incomingServerSettings, outgoingServerSettings, authState, options -> createAccountEmailAddress = emailAddress @@ -44,7 +44,7 @@ class AccountSetupViewModelTest { "accountUuid" }, - accountSetupStateRepository = accountSetupStateRepository, + accountStateRepository = accountStateRepository, ) val turbines = turbinesWithInitialStateCheck(viewModel, State(setupStep = SetupStep.AUTO_CONFIG)) @@ -54,7 +54,7 @@ class AccountSetupViewModelTest { ), ) - val expectedAccountSetupState = AccountSetupState( + val expectedAccountState = AccountState( emailAddress = "test@domain.example", incomingServerSettings = ServerSettings( type = "imap", @@ -132,7 +132,7 @@ class AccountSetupViewModelTest { prop(State::setupStep).isEqualTo(SetupStep.OPTIONS) } - accountSetupStateRepository.save(expectedAccountSetupState) + accountStateRepository.save(expectedAccountState) viewModel.event(AccountSetupContract.Event.OnNext) @@ -144,10 +144,10 @@ class AccountSetupViewModelTest { } assertThat(createAccountEmailAddress).isEqualTo(EMAIL_ADDRESS) - assertThat(createAccountIncomingServerSettings).isEqualTo(expectedAccountSetupState.incomingServerSettings) - assertThat(createAccountOutgoingServerSettings).isEqualTo(expectedAccountSetupState.outgoingServerSettings) + assertThat(createAccountIncomingServerSettings).isEqualTo(expectedAccountState.incomingServerSettings) + assertThat(createAccountOutgoingServerSettings).isEqualTo(expectedAccountState.outgoingServerSettings) assertThat(createAccountAuthorizationState).isNull() - assertThat(createAccountOptions).isEqualTo(expectedAccountSetupState.options) + assertThat(createAccountOptions).isEqualTo(expectedAccountState.options) } @Test @@ -155,7 +155,7 @@ class AccountSetupViewModelTest { val initialState = State(setupStep = SetupStep.OPTIONS) val viewModel = AccountSetupViewModel( createAccount = { _, _, _, _, _ -> "accountUuid" }, - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), initialState = initialState, ) val turbines = turbinesWithInitialStateCheck(viewModel, initialState) @@ -205,7 +205,7 @@ class AccountSetupViewModelTest { ) val viewModel = AccountSetupViewModel( createAccount = { _, _, _, _, _ -> "accountUuid" }, - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), initialState = initialState, ) val turbines = turbinesWithInitialStateCheck(viewModel, initialState) @@ -237,7 +237,7 @@ class AccountSetupViewModelTest { ) val viewModel = AccountSetupViewModel( createAccount = { _, _, _, _, _ -> "accountUuid" }, - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), initialState = initialState, ) val turbines = turbinesWithInitialStateCheck(viewModel, initialState) @@ -269,7 +269,7 @@ class AccountSetupViewModelTest { ) val viewModel = AccountSetupViewModel( createAccount = { _, _, _, _, _ -> "accountUuid" }, - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), initialState = initialState, ) val turbines = turbinesWithInitialStateCheck(viewModel, initialState) diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt index 6615b5019b..05f99c2e16 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt @@ -5,7 +5,7 @@ import app.k9mail.autodiscovery.api.ImapServerSettings import app.k9mail.autodiscovery.api.SmtpServerSettings import app.k9mail.core.common.net.toHostname import app.k9mail.core.common.net.toPort -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity @@ -23,11 +23,11 @@ import org.junit.Test class AccountAutoDiscoveryStateMapperKtTest { @Test - fun `should map to empty AccountSetupState when empty`() { - val accountSetupState = EMPTY_STATE.toAccountSetupState() + fun `should map to empty AccountState when empty`() { + val accountState = EMPTY_STATE.toAccountState() - assertThat(accountSetupState).isEqualTo( - AccountSetupState( + assertThat(accountState).isEqualTo( + AccountState( emailAddress = "", incomingServerSettings = null, outgoingServerSettings = null, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt index 7099eb6dce..3f13d83dcb 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt @@ -7,9 +7,9 @@ import app.k9mail.core.ui.compose.testing.MainDispatcherRule import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.eventStateTest import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck -import app.k9mail.feature.account.setup.data.InMemoryAccountSetupStateRepository -import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.setup.domain.entity.AutoDiscoverySettingsFixture import app.k9mail.feature.account.setup.domain.input.BooleanInputField import app.k9mail.feature.account.setup.domain.input.StringInputField @@ -94,7 +94,7 @@ class AccountAutoDiscoveryViewModelTest { autoDiscoverySettings }, oAuthViewModel = FakeAccountOAuthViewModel(), - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), initialState = initialState, ) val turbines = turbinesWithInitialStateCheck(testSubject, initialState) @@ -143,7 +143,7 @@ class AccountAutoDiscoveryViewModelTest { AutoDiscoveryResult.UnexpectedException(discoveryError) }, oAuthViewModel = FakeAccountOAuthViewModel(), - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), initialState = initialState, ) val turbines = turbinesWithInitialStateCheck(testSubject, initialState) @@ -217,7 +217,7 @@ class AccountAutoDiscoveryViewModelTest { ), getAutoDiscovery = { AutoDiscoveryResult.NoUsableSettingsFound }, oAuthViewModel = FakeAccountOAuthViewModel(), - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), initialState = initialState, ) @@ -245,7 +245,7 @@ class AccountAutoDiscoveryViewModelTest { emailAddress = StringInputField(value = "email"), password = StringInputField(value = "password"), ) - val repository = InMemoryAccountSetupStateRepository() + val repository = InMemoryAccountStateRepository() val testSubject = createTestSubject( initialState = initialState, repository = repository, @@ -283,7 +283,7 @@ class AccountAutoDiscoveryViewModelTest { } assertThat(repository.getState()).isEqualTo( - AccountSetupState( + AccountState( emailAddress = "email", incomingServerSettings = null, outgoingServerSettings = null, @@ -307,7 +307,7 @@ class AccountAutoDiscoveryViewModelTest { ), getAutoDiscovery = { AutoDiscoveryResult.NoUsableSettingsFound }, oAuthViewModel = FakeAccountOAuthViewModel(), - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), initialState = initialState, ) val turbines = turbinesWithInitialStateCheck(viewModel, initialState) @@ -431,7 +431,7 @@ class AccountAutoDiscoveryViewModelTest { private companion object { fun createTestSubject( initialState: State = State(), - repository: DomainContract.AccountSetupStateRepository = InMemoryAccountSetupStateRepository(), + repository: AccountDomainContract.AccountStateRepository = InMemoryAccountStateRepository(), ): AccountAutoDiscoveryViewModel { return AccountAutoDiscoveryViewModel( validator = FakeAccountAutoDiscoveryValidator(), @@ -439,7 +439,7 @@ class AccountAutoDiscoveryViewModelTest { delay(50) AutoDiscoveryResult.NoUsableSettingsFound }, - accountSetupStateRepository = repository, + accountStateRepository = repository, oAuthViewModel = FakeAccountOAuthViewModel(), initialState = initialState, ) diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt index fa63509496..e37fa01a7c 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt @@ -1,9 +1,9 @@ package app.k9mail.feature.account.setup.ui.incoming +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType -import app.k9mail.feature.account.setup.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.domain.input.NumberInputField import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt index cd0b35cdab..77b6f0a7ed 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt @@ -7,13 +7,13 @@ import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.eventStateTest import app.k9mail.core.ui.compose.testing.mvi.turbines import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck -import app.k9mail.feature.account.setup.data.InMemoryAccountSetupStateRepository -import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType -import app.k9mail.feature.account.setup.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toImapDefaultPort import app.k9mail.feature.account.setup.domain.entity.toPop3DefaultPort import app.k9mail.feature.account.setup.domain.input.NumberInputField @@ -36,7 +36,7 @@ class AccountIncomingConfigViewModelTest { @Test fun `should take initial state from repository when no initial state is provided`() = runTest { - val accountSetupState = AccountSetupState( + val accountState = AccountState( emailAddress = "test@example.com", incomingServerSettings = ServerSettings( "imap", @@ -52,7 +52,7 @@ class AccountIncomingConfigViewModelTest { ) val testSubject = createTestSubject( initialState = null, - repository = InMemoryAccountSetupStateRepository(accountSetupState), + repository = InMemoryAccountStateRepository(accountState), ) val turbines = turbines(testSubject) @@ -75,8 +75,8 @@ class AccountIncomingConfigViewModelTest { } @Test - fun `should load account setup state when LoadAccountSetupState event is received`() = runTest { - val accountSetupState = AccountSetupState( + fun `should load account setup state when LoadAccountState event is received`() = runTest { + val accountState = AccountState( emailAddress = "test@example.com", incomingServerSettings = ServerSettings( "imap", @@ -90,16 +90,16 @@ class AccountIncomingConfigViewModelTest { extra = emptyMap(), ), ) - val repository = InMemoryAccountSetupStateRepository(AccountSetupState()) + val repository = InMemoryAccountStateRepository(AccountState()) val testSubject = createTestSubject( initialState = null, repository = repository, ) val turbines = turbinesWithInitialStateCheck(testSubject, State()) - repository.save(accountSetupState) + repository.save(accountState) - testSubject.event(Event.LoadAccountSetupState) + testSubject.event(Event.LoadAccountState) assertThatAndMviTurbinesConsumed( actual = turbines.awaitStateItem(), @@ -278,7 +278,7 @@ class AccountIncomingConfigViewModelTest { @Test fun `should save state emit effect NavigateNext when OnNextClicked is received and input valid`() = runTest { val initialState = State() - val repository = InMemoryAccountSetupStateRepository() + val repository = InMemoryAccountStateRepository() val testSubject = createTestSubject( initialState = initialState, repository = repository, @@ -300,7 +300,7 @@ class AccountIncomingConfigViewModelTest { ) assertThat(repository.getState()).isEqualTo( - AccountSetupState( + AccountState( incomingServerSettings = ServerSettings( type = "imap", host = "", @@ -334,7 +334,7 @@ class AccountIncomingConfigViewModelTest { val initialState = State( authenticationType = AuthenticationType.OAuth2, ) - val repository = InMemoryAccountSetupStateRepository() + val repository = InMemoryAccountStateRepository() val testSubject = createTestSubject( initialState = initialState, repository = repository, @@ -356,7 +356,7 @@ class AccountIncomingConfigViewModelTest { ) assertThat(repository.getState()).isEqualTo( - AccountSetupState( + AccountState( emailAddress = null, incomingServerSettings = ServerSettings( type = "imap", @@ -392,7 +392,7 @@ class AccountIncomingConfigViewModelTest { validator = FakeAccountIncomingConfigValidator( serverAnswer = ValidationResult.Failure(TestError), ), - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), ) val turbines = turbinesWithInitialStateCheck(testSubject, State()) @@ -435,10 +435,10 @@ class AccountIncomingConfigViewModelTest { fun createTestSubject( initialState: State? = null, validator: AccountIncomingConfigContract.Validator = FakeAccountIncomingConfigValidator(), - repository: DomainContract.AccountSetupStateRepository = InMemoryAccountSetupStateRepository(), + repository: AccountDomainContract.AccountStateRepository = InMemoryAccountStateRepository(), ) = AccountIncomingConfigViewModel( validator = validator, - accountSetupStateRepository = repository, + accountStateRepository = repository, initialState = initialState, ) } diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapperKtTest.kt index 4ef8082def..84b9991741 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapperKtTest.kt @@ -1,6 +1,6 @@ package app.k9mail.feature.account.setup.ui.options -import app.k9mail.feature.account.setup.domain.entity.AccountOptions +import app.k9mail.feature.account.common.domain.entity.AccountOptions import app.k9mail.feature.account.setup.domain.entity.EmailCheckFrequency import app.k9mail.feature.account.setup.domain.entity.EmailDisplayCount import app.k9mail.feature.account.setup.domain.input.StringInputField diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModelTest.kt index a47689aca0..3b9ff7d657 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModelTest.kt @@ -5,7 +5,7 @@ import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.testing.MainDispatcherRule import app.k9mail.core.ui.compose.testing.mvi.eventStateTest -import app.k9mail.feature.account.setup.data.InMemoryAccountSetupStateRepository +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.setup.domain.entity.EmailCheckFrequency import app.k9mail.feature.account.setup.domain.entity.EmailDisplayCount import app.k9mail.feature.account.setup.domain.input.StringInputField @@ -15,12 +15,10 @@ import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.State import assertk.assertThat import assertk.assertions.assertThatAndTurbinesConsumed import assertk.assertions.isEqualTo -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -@OptIn(ExperimentalCoroutinesApi::class) class AccountOptionsViewModelTest { @get:Rule @@ -28,7 +26,7 @@ class AccountOptionsViewModelTest { private val testSubject = AccountOptionsViewModel( validator = FakeAccountOptionsValidator(), - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), ) @Test @@ -137,7 +135,7 @@ class AccountOptionsViewModelTest { validator = FakeAccountOptionsValidator( accountNameAnswer = ValidationResult.Failure(TestError), ), - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), ) val stateTurbine = viewModel.state.testIn(backgroundScope) val effectTurbine = viewModel.effect.testIn(backgroundScope) diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt index b4d47c10f1..53eec173b6 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt @@ -1,8 +1,8 @@ package app.k9mail.feature.account.setup.ui.outgoing +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.domain.input.NumberInputField import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt index 1d6c57625b..881ae5b65e 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt @@ -7,12 +7,12 @@ import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.eventStateTest import app.k9mail.core.ui.compose.testing.mvi.turbines import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck -import app.k9mail.feature.account.setup.data.InMemoryAccountSetupStateRepository -import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.setup.domain.input.NumberInputField import app.k9mail.feature.account.setup.domain.input.StringInputField @@ -34,7 +34,7 @@ class AccountOutgoingConfigViewModelTest { @Test fun `should take initial state from repository when no initial state is provided`() = runTest { - val accountSetupState = AccountSetupState( + val accountState = AccountState( emailAddress = "test@example.com", outgoingServerSettings = ServerSettings( "smtp", @@ -50,7 +50,7 @@ class AccountOutgoingConfigViewModelTest { ) val testSubject = createTestSubject( initialState = null, - repository = InMemoryAccountSetupStateRepository(accountSetupState), + repository = InMemoryAccountStateRepository(accountState), ) val turbines = turbines(testSubject) @@ -72,8 +72,8 @@ class AccountOutgoingConfigViewModelTest { } @Test - fun `should load account setup state when LoadAccountSetupState event is received`() = runTest { - val accountSetupState = AccountSetupState( + fun `should load account setup state when LoadAccountState event is received`() = runTest { + val accountState = AccountState( emailAddress = "test@example.com", outgoingServerSettings = ServerSettings( "smtp", @@ -87,16 +87,16 @@ class AccountOutgoingConfigViewModelTest { extra = emptyMap(), ), ) - val repository = InMemoryAccountSetupStateRepository(AccountSetupState()) + val repository = InMemoryAccountStateRepository(AccountState()) val testSubject = createTestSubject( initialState = null, repository = repository, ) val turbines = turbinesWithInitialStateCheck(testSubject, State()) - repository.save(accountSetupState) + repository.save(accountState) - testSubject.event(Event.LoadAccountSetupState) + testSubject.event(Event.LoadAccountState) assertThatAndMviTurbinesConsumed( actual = turbines.awaitStateItem(), @@ -198,7 +198,7 @@ class AccountOutgoingConfigViewModelTest { @Test fun `should save state and emit effect NavigateNext when OnNextClicked is received and input valid`() = runTest { val initialState = State() - val repository = InMemoryAccountSetupStateRepository() + val repository = InMemoryAccountStateRepository() val testSubject = createTestSubject( initialState = initialState, repository = repository, @@ -218,7 +218,7 @@ class AccountOutgoingConfigViewModelTest { ) assertThat(repository.getState()).isEqualTo( - AccountSetupState( + AccountState( outgoingServerSettings = ServerSettings( type = "smtp", host = "", @@ -247,7 +247,7 @@ class AccountOutgoingConfigViewModelTest { val initialState = State( authenticationType = AuthenticationType.OAuth2, ) - val repository = InMemoryAccountSetupStateRepository() + val repository = InMemoryAccountStateRepository() val testSubject = createTestSubject( initialState = initialState, repository = repository, @@ -267,7 +267,7 @@ class AccountOutgoingConfigViewModelTest { ) assertThat(repository.getState()).isEqualTo( - AccountSetupState( + AccountState( outgoingServerSettings = ServerSettings( type = "smtp", host = "", @@ -341,10 +341,10 @@ class AccountOutgoingConfigViewModelTest { fun createTestSubject( initialState: State? = null, validator: AccountOutgoingConfigContract.Validator = FakeAccountOutgoingConfigValidator(), - repository: DomainContract.AccountSetupStateRepository = InMemoryAccountSetupStateRepository(), + repository: AccountDomainContract.AccountStateRepository = InMemoryAccountStateRepository(), ) = AccountOutgoingConfigViewModel( validator = validator, - accountSetupStateRepository = repository, + accountStateRepository = repository, initialState = initialState, ) } diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt index f64341ded1..10ae448644 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt @@ -3,9 +3,9 @@ package app.k9mail.feature.account.setup.ui.validation import app.k9mail.core.ui.compose.testing.MainDispatcherRule import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck -import app.k9mail.feature.account.setup.data.InMemoryAccountSetupStateRepository +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository -import app.k9mail.feature.account.setup.domain.entity.AccountSetupState import app.k9mail.feature.account.setup.ui.FakeAccountOAuthViewModel import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Error @@ -29,8 +29,8 @@ class AccountValidationViewModelTest { val mainDispatcherRule = MainDispatcherRule() @Test - fun `should update state when LoadAccountSetupStateAndValidate event received and validate`() = runTest { - val accountSetupState = AccountSetupState( + fun `should update state when LoadAccountStateAndValidate event received and validate`() = runTest { + val accountState = AccountState( incomingServerSettings = IMAP_SERVER_SETTINGS, ) val initialState = State( @@ -40,7 +40,7 @@ class AccountValidationViewModelTest { isSuccess = true, ) val testSubject = createTestSubject( - accountSetupState = accountSetupState, + accountState = accountState, initialState = initialState, ) @@ -53,7 +53,7 @@ class AccountValidationViewModelTest { isSuccess = false, ) - testSubject.event(Event.LoadAccountSetupStateAndValidate) + testSubject.event(Event.LoadAccountStateAndValidate) assertThat(turbines.awaitStateItem()).isEqualTo(expectedState) @@ -197,7 +197,7 @@ class AccountValidationViewModelTest { checkSettingsCalled = true ServerSettingsValidationResult.Success }, - accountSetupStateRepository = InMemoryAccountSetupStateRepository(), + accountStateRepository = InMemoryAccountStateRepository(), authorizationStateRepository = { true }, certificateErrorRepository = InMemoryCertificateErrorRepository(), oAuthViewModel = FakeAccountOAuthViewModel(), @@ -228,7 +228,7 @@ class AccountValidationViewModelTest { private companion object { fun createTestSubject( serverSettingsValidationResult: ServerSettingsValidationResult = ServerSettingsValidationResult.Success, - accountSetupState: AccountSetupState = AccountSetupState(), + accountState: AccountState = AccountState(), initialState: State = State(), ): AccountValidationViewModel { return AccountValidationViewModel( @@ -236,7 +236,7 @@ class AccountValidationViewModelTest { delay(50) serverSettingsValidationResult }, - accountSetupStateRepository = InMemoryAccountSetupStateRepository(accountSetupState), + accountStateRepository = InMemoryAccountStateRepository(accountState), authorizationStateRepository = { true }, certificateErrorRepository = InMemoryCertificateErrorRepository(), oAuthViewModel = FakeAccountOAuthViewModel(), diff --git a/settings.gradle.kts b/settings.gradle.kts index b545cd024e..3fdff2363d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -40,10 +40,16 @@ include( include( ":feature:launcher", + ":feature:onboarding", +) + +include( ":feature:account:common", - ":feature:account:setup", ":feature:account:oauth", - ":feature:onboarding", + ":feature:account:setup", +) + +include( ":feature:autodiscovery:api", ":feature:autodiscovery:providersxml", ":feature:autodiscovery:srvrecords", -- GitLab From 385de5fdebb8c89c94db8c44f372cda8b342e20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Thu, 31 Aug 2023 19:14:46 +0200 Subject: [PATCH 08/94] Rename account oauth DomainContract to AccountOAuthDomainContract --- .../com/fsck/k9/activity/setup/AccountSetupAccountType.kt | 2 +- .../com/fsck/k9/activity/setup/AccountSetupIncoming.java | 2 +- .../main/java/com/fsck/k9/activity/setup/AuthViewModel.kt | 2 +- .../k9mail/feature/account/oauth/AccountOAuthModule.kt | 8 ++++---- .../feature/account/oauth/data/AuthorizationRepository.kt | 4 ++-- .../account/oauth/data/AuthorizationStateRepository.kt | 4 ++-- .../{DomainContract.kt => AccountOAuthDomainContract.kt} | 2 +- .../account/oauth/domain/usecase/CheckIsGoogleSignIn.kt | 2 +- .../account/oauth/domain/usecase/FinishOAuthSignIn.kt | 6 +++--- .../account/oauth/domain/usecase/GetOAuthRequestIntent.kt | 6 +++--- .../account/oauth/domain/usecase/SuggestServerName.kt | 2 +- .../feature/account/oauth/ui/AccountOAuthViewModel.kt | 2 +- .../account/oauth/domain/FakeAuthorizationRepository.kt | 2 +- .../setup/ui/validation/AccountValidationViewModel.kt | 4 ++-- 14 files changed, 24 insertions(+), 24 deletions(-) rename feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/{DomainContract.kt => AccountOAuthDomainContract.kt} (97%) diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupAccountType.kt b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupAccountType.kt index 29d1b105fb..891d2cc830 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupAccountType.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupAccountType.kt @@ -5,7 +5,7 @@ import android.content.Intent import android.os.Bundle import android.view.View import app.k9mail.core.common.mail.Protocols -import app.k9mail.feature.account.oauth.domain.DomainContract.UseCase.SuggestServerName +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract.UseCase.SuggestServerName import com.fsck.k9.Account import com.fsck.k9.Preferences import com.fsck.k9.helper.EmailHelper.getDomainFromEmailAddress diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupIncoming.java b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupIncoming.java index fb0a106569..5d73e6564b 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupIncoming.java +++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupIncoming.java @@ -27,7 +27,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import app.k9mail.core.common.mail.Protocols; -import app.k9mail.feature.account.oauth.domain.DomainContract.UseCase.SuggestServerName; +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract.UseCase.SuggestServerName; import com.fsck.k9.Account; import com.fsck.k9.DI; import com.fsck.k9.LocalKeyStoreManager; diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AuthViewModel.kt b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AuthViewModel.kt index d4278c660b..8c13857428 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AuthViewModel.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AuthViewModel.kt @@ -13,7 +13,7 @@ import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.viewModelScope -import app.k9mail.feature.account.oauth.domain.DomainContract.UseCase.GetOAuthRequestIntent +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract.UseCase.GetOAuthRequestIntent import app.k9mail.feature.account.oauth.domain.entity.AuthorizationIntentResult import com.fsck.k9.Account import com.fsck.k9.preferences.AccountManager diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/AccountOAuthModule.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/AccountOAuthModule.kt index 23f1b90792..e7df9c80d7 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/AccountOAuthModule.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/AccountOAuthModule.kt @@ -3,8 +3,8 @@ package app.k9mail.feature.account.oauth import app.k9mail.core.common.coreCommonModule import app.k9mail.feature.account.oauth.data.AuthorizationRepository import app.k9mail.feature.account.oauth.data.AuthorizationStateRepository -import app.k9mail.feature.account.oauth.domain.DomainContract -import app.k9mail.feature.account.oauth.domain.DomainContract.UseCase +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract.UseCase import app.k9mail.feature.account.oauth.domain.usecase.CheckIsGoogleSignIn import app.k9mail.feature.account.oauth.domain.usecase.FinishOAuthSignIn import app.k9mail.feature.account.oauth.domain.usecase.GetOAuthRequestIntent @@ -25,13 +25,13 @@ val featureAccountOAuthModule: Module = module { ) } - factory { + factory { AuthorizationRepository( service = get(), ) } - factory { + factory { AuthorizationStateRepository() } diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepository.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepository.kt index 5617d36c28..0cbba30156 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepository.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepository.kt @@ -3,7 +3,7 @@ package app.k9mail.feature.account.oauth.data import android.content.Intent import androidx.core.net.toUri import app.k9mail.core.common.oauth.OAuthConfiguration -import app.k9mail.feature.account.oauth.domain.DomainContract +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract import app.k9mail.feature.account.oauth.domain.entity.AuthorizationIntentResult import app.k9mail.feature.account.oauth.domain.entity.AuthorizationResult import kotlin.coroutines.resume @@ -19,7 +19,7 @@ import timber.log.Timber class AuthorizationRepository( private val service: AuthorizationService, -) : DomainContract.AuthorizationRepository { +) : AccountOAuthDomainContract.AuthorizationRepository { override fun getAuthorizationRequestIntent( configuration: OAuthConfiguration, diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationStateRepository.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationStateRepository.kt index 811ce67c7a..86976aebac 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationStateRepository.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationStateRepository.kt @@ -1,9 +1,9 @@ package app.k9mail.feature.account.oauth.data import app.k9mail.feature.account.common.domain.entity.AuthorizationState -import app.k9mail.feature.account.oauth.domain.DomainContract +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract -class AuthorizationStateRepository : DomainContract.AuthorizationStateRepository { +class AuthorizationStateRepository : AccountOAuthDomainContract.AuthorizationStateRepository { override fun isAuthorized(authorizationState: AuthorizationState): Boolean { val authState = authorizationState.toAuthState() diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/DomainContract.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/AccountOAuthDomainContract.kt similarity index 97% rename from feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/DomainContract.kt rename to feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/AccountOAuthDomainContract.kt index 1afaaa28dc..2a456ccebe 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/DomainContract.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/AccountOAuthDomainContract.kt @@ -8,7 +8,7 @@ import app.k9mail.feature.account.oauth.domain.entity.AuthorizationResult import net.openid.appauth.AuthorizationException import net.openid.appauth.AuthorizationResponse -interface DomainContract { +interface AccountOAuthDomainContract { interface UseCase { fun interface SuggestServerName { diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/CheckIsGoogleSignIn.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/CheckIsGoogleSignIn.kt index c395e468d6..7bc325e27c 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/CheckIsGoogleSignIn.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/CheckIsGoogleSignIn.kt @@ -1,6 +1,6 @@ package app.k9mail.feature.account.oauth.domain.usecase -import app.k9mail.feature.account.oauth.domain.DomainContract.UseCase +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract.UseCase internal class CheckIsGoogleSignIn : UseCase.CheckIsGoogleSignIn { override fun execute(hostname: String): Boolean { diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/FinishOAuthSignIn.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/FinishOAuthSignIn.kt index 8b22d8fa04..6257d107e2 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/FinishOAuthSignIn.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/FinishOAuthSignIn.kt @@ -1,12 +1,12 @@ package app.k9mail.feature.account.oauth.domain.usecase import android.content.Intent -import app.k9mail.feature.account.oauth.domain.DomainContract -import app.k9mail.feature.account.oauth.domain.DomainContract.UseCase +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract.UseCase import app.k9mail.feature.account.oauth.domain.entity.AuthorizationResult class FinishOAuthSignIn( - private val repository: DomainContract.AuthorizationRepository, + private val repository: AccountOAuthDomainContract.AuthorizationRepository, ) : UseCase.FinishOAuthSignIn { override suspend fun execute(intent: Intent): AuthorizationResult { val response = repository.getAuthorizationResponse(intent) diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/GetOAuthRequestIntent.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/GetOAuthRequestIntent.kt index ac8ad0f03c..0d38a05132 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/GetOAuthRequestIntent.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/GetOAuthRequestIntent.kt @@ -1,12 +1,12 @@ package app.k9mail.feature.account.oauth.domain.usecase import app.k9mail.core.common.oauth.OAuthConfigurationProvider -import app.k9mail.feature.account.oauth.domain.DomainContract -import app.k9mail.feature.account.oauth.domain.DomainContract.UseCase.GetOAuthRequestIntent +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract.UseCase.GetOAuthRequestIntent import app.k9mail.feature.account.oauth.domain.entity.AuthorizationIntentResult internal class GetOAuthRequestIntent( - private val repository: DomainContract.AuthorizationRepository, + private val repository: AccountOAuthDomainContract.AuthorizationRepository, private val configurationProvider: OAuthConfigurationProvider, ) : GetOAuthRequestIntent { override fun execute(hostname: String, emailAddress: String): AuthorizationIntentResult { diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/SuggestServerName.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/SuggestServerName.kt index 6125730642..5744fba346 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/SuggestServerName.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/domain/usecase/SuggestServerName.kt @@ -1,7 +1,7 @@ package app.k9mail.feature.account.oauth.domain.usecase import app.k9mail.core.common.mail.Protocols -import app.k9mail.feature.account.oauth.domain.DomainContract.UseCase +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract.UseCase @Deprecated("This is not needed anymore, remove once auth setup flow is updated") class SuggestServerName : UseCase.SuggestServerName { diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModel.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModel.kt index e92e3eb7bd..8ea109d974 100644 --- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModel.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/AccountOAuthViewModel.kt @@ -5,7 +5,7 @@ import android.content.Intent import androidx.lifecycle.viewModelScope import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.common.domain.entity.AuthorizationState -import app.k9mail.feature.account.oauth.domain.DomainContract.UseCase +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract.UseCase import app.k9mail.feature.account.oauth.domain.entity.AuthorizationIntentResult import app.k9mail.feature.account.oauth.domain.entity.AuthorizationResult import app.k9mail.feature.account.oauth.ui.AccountOAuthContract.Effect diff --git a/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/domain/FakeAuthorizationRepository.kt b/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/domain/FakeAuthorizationRepository.kt index 7c5d4c0f98..ceb16b4e53 100644 --- a/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/domain/FakeAuthorizationRepository.kt +++ b/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/domain/FakeAuthorizationRepository.kt @@ -12,7 +12,7 @@ class FakeAuthorizationRepository( private val answerGetAuthorizationResponse: AuthorizationResponse? = null, private val answerGetAuthorizationException: AuthorizationException? = null, private val answerGetExchangeToken: AuthorizationResult = AuthorizationResult.Canceled, -) : DomainContract.AuthorizationRepository { +) : AccountOAuthDomainContract.AuthorizationRepository { var recordedGetAuthorizationRequestIntentConfiguration: OAuthConfiguration? = null var recordedGetAuthorizationRequestIntentEmailAddress: String? = null diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt index 59895e0663..c7003ac4bf 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt @@ -3,6 +3,7 @@ package app.k9mail.feature.account.setup.ui.validation import androidx.lifecycle.viewModelScope import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.setup.domain.DomainContract @@ -16,7 +17,6 @@ import com.fsck.k9.mail.server.ServerSettingsValidationResult import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import app.k9mail.feature.account.oauth.domain.DomainContract as OAuthDomainContract private const val CONTINUE_NEXT_DELAY = 2000L @@ -24,7 +24,7 @@ private const val CONTINUE_NEXT_DELAY = 2000L internal class AccountValidationViewModel( private val validateServerSettings: DomainContract.UseCase.ValidateServerSettings, private val accountStateRepository: AccountDomainContract.AccountStateRepository, - private val authorizationStateRepository: OAuthDomainContract.AuthorizationStateRepository, + private val authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, private val certificateErrorRepository: DomainContract.CertificateErrorRepository, override val oAuthViewModel: AccountOAuthContract.ViewModel, override val isIncomingValidation: Boolean = true, -- GitLab From 3cc3918ef3fcdba9cf74447f351de0f60ed5892a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Thu, 31 Aug 2023 19:27:56 +0200 Subject: [PATCH 09/94] Add RealOAuth2TokenProvider to feature app to prevent it from crashing --- app-feature-preview/build.gradle.kts | 2 + .../k9mail/feature/preview/FeatureModule.kt | 3 + .../backend/RealOAuth2TokenProvider.kt | 91 +++++++++++++++++++ .../backend/RealOAuth2TokenProviderFactory.kt | 14 +++ 4 files changed, 110 insertions(+) create mode 100644 app-feature-preview/src/main/java/app/k9mail/feature/preview/backend/RealOAuth2TokenProvider.kt create mode 100644 app-feature-preview/src/main/java/app/k9mail/feature/preview/backend/RealOAuth2TokenProviderFactory.kt diff --git a/app-feature-preview/build.gradle.kts b/app-feature-preview/build.gradle.kts index b601ae760f..a37b72158a 100644 --- a/app-feature-preview/build.gradle.kts +++ b/app-feature-preview/build.gradle.kts @@ -70,6 +70,8 @@ dependencies { implementation(projects.feature.onboarding) implementation(projects.feature.account.setup) + + implementation(libs.appauth) implementation(libs.okhttp) implementation(libs.timber) } diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt index 23dd89e994..5edb78b6cd 100644 --- a/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt @@ -8,6 +8,8 @@ import app.k9mail.feature.preview.account.AccountOwnerNameProvider import app.k9mail.feature.preview.auth.AndroidKeyStoreDirectoryProvider import app.k9mail.feature.preview.auth.AppOAuthConfigurationFactory import app.k9mail.feature.preview.auth.DefaultTrustedSocketFactory +import app.k9mail.feature.preview.backend.RealOAuth2TokenProviderFactory +import com.fsck.k9.mail.oauth.OAuth2TokenProviderFactory import com.fsck.k9.mail.ssl.KeyStoreDirectoryProvider import com.fsck.k9.mail.ssl.LocalKeyStore import com.fsck.k9.mail.ssl.TrustManagerFactory @@ -27,6 +29,7 @@ val featureModule: Module = module { single { LocalKeyStore(directoryProvider = get()) } single { TrustManagerFactory.createInstance(get()) } single { DefaultTrustedSocketFactory(get(), get()) } + single { RealOAuth2TokenProviderFactory(context = get()) } includes(featureAccountSetupModule, accountModule) } diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/backend/RealOAuth2TokenProvider.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/backend/RealOAuth2TokenProvider.kt new file mode 100644 index 0000000000..eb160dff95 --- /dev/null +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/backend/RealOAuth2TokenProvider.kt @@ -0,0 +1,91 @@ +package app.k9mail.feature.preview.backend + +import android.content.Context +import app.k9mail.feature.preview.BuildConfig +import com.fsck.k9.mail.AuthenticationFailedException +import com.fsck.k9.mail.oauth.AuthStateStorage +import com.fsck.k9.mail.oauth.OAuth2TokenProvider +import java.io.IOException +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import net.openid.appauth.AuthState +import net.openid.appauth.AuthorizationException +import net.openid.appauth.AuthorizationException.AuthorizationRequestErrors +import net.openid.appauth.AuthorizationException.GeneralErrors +import net.openid.appauth.AuthorizationService +import timber.log.Timber + +class RealOAuth2TokenProvider( + context: Context, + private val authStateStorage: AuthStateStorage, +) : OAuth2TokenProvider { + private val authService = AuthorizationService(context) + private var requestFreshToken = false + + @Suppress("TooGenericExceptionCaught") + override fun getToken(timeoutMillis: Long): String { + val latch = CountDownLatch(1) + var token: String? = null + var exception: AuthorizationException? = null + + val authState = authStateStorage.getAuthorizationState()?.let { AuthState.jsonDeserialize(it) } + ?: throw AuthenticationFailedException("Login required") + + if (requestFreshToken) { + authState.needsTokenRefresh = true + } + + val oldAccessToken = authState.accessToken + + try { + authState.performActionWithFreshTokens(authService) { accessToken: String?, _, authException: AuthorizationException? -> + token = accessToken + exception = authException + + latch.countDown() + } + + latch.await(timeoutMillis, TimeUnit.MILLISECONDS) + } catch (e: Exception) { + // OAuth errors are communicated via the callback. If we end up here, it's probably a programming error. + if (BuildConfig.DEBUG) { + throw AssertionError("Wrong usage of AuthState.performActionWithFreshTokens()?", e) + } + + Timber.w(e, "Failed to fetch an access token. Clearing authorization state.") + + authStateStorage.updateAuthorizationState(authorizationState = null) + + throw AuthenticationFailedException( + message = "Failed to fetch an access token", + throwable = e, + ) + } + + val authException = exception + if (authException == GeneralErrors.NETWORK_ERROR || + authException == GeneralErrors.SERVER_ERROR || + authException == AuthorizationRequestErrors.SERVER_ERROR || + authException == AuthorizationRequestErrors.TEMPORARILY_UNAVAILABLE + ) { + throw IOException("Error while fetching an access token", authException) + } else if (authException != null) { + authStateStorage.updateAuthorizationState(authorizationState = null) + + throw AuthenticationFailedException( + message = "Failed to fetch an access token", + throwable = authException, + messageFromServer = authException.error, + ) + } else if (token != oldAccessToken) { + requestFreshToken = false + authStateStorage.updateAuthorizationState(authorizationState = authState.jsonSerializeString()) + } + + return token ?: throw AuthenticationFailedException("Failed to fetch an access token") + } + + override fun invalidateToken() { + requestFreshToken = true + } +} diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/backend/RealOAuth2TokenProviderFactory.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/backend/RealOAuth2TokenProviderFactory.kt new file mode 100644 index 0000000000..4768662595 --- /dev/null +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/backend/RealOAuth2TokenProviderFactory.kt @@ -0,0 +1,14 @@ +package app.k9mail.feature.preview.backend + +import android.content.Context +import com.fsck.k9.mail.oauth.AuthStateStorage +import com.fsck.k9.mail.oauth.OAuth2TokenProvider +import com.fsck.k9.mail.oauth.OAuth2TokenProviderFactory + +class RealOAuth2TokenProviderFactory( + private val context: Context, +) : OAuth2TokenProviderFactory { + override fun create(authStateStorage: AuthStateStorage): OAuth2TokenProvider { + return RealOAuth2TokenProvider(context, authStateStorage) + } +} -- GitLab From 795b5a42eacfb4da2032b7aeb9d46d83b2ca0295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Fri, 1 Sep 2023 11:52:05 +0200 Subject: [PATCH 10/94] Add servercertificate module and move code from setup there --- .../servercertificate/build.gradle.kts | 18 ++++++++++ .../AccountServerCertificateModule.kt | 29 +++++++++++++++ ...nMemoryServerCertificateErrorRepository.kt | 21 +++++++++++ .../AccountServerCertificateDomainContract.kt | 21 +++++++++++ .../domain/entity/ServerCertificateError.kt} | 4 +-- .../usecase/AddServerCertificateException.kt | 6 ++-- .../AccountServerCertificateErrorContract.kt} | 4 +-- .../AccountServerCertificateErrorScreen.kt} | 22 ++++++------ ...AccountServerCertificateErrorViewModel.kt} | 32 ++++++++--------- .../AccountServerCertificateModuleKtTest.kt | 35 +++++++++++++++++++ feature/account/setup/build.gradle.kts | 3 ++ .../account/setup/AccountSetupModule.kt | 20 ++--------- .../InMemoryCertificateErrorRepository.kt | 21 ----------- .../account/setup/domain/DomainContract.kt | 9 ----- .../validation/AccountValidationMainScreen.kt | 10 +++--- .../ui/validation/AccountValidationScreen.kt | 2 +- .../validation/AccountValidationViewModel.kt | 7 ++-- .../account/setup/AccountSetupModuleKtTest.kt | 4 +-- .../AccountValidationViewModelTest.kt | 6 ++-- settings.gradle.kts | 1 + 20 files changed, 179 insertions(+), 96 deletions(-) create mode 100644 feature/account/servercertificate/build.gradle.kts create mode 100644 feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt create mode 100644 feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt create mode 100644 feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/CertificateError.kt => servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt} (57%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate}/domain/usecase/AddServerCertificateException.kt (73%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorContract.kt => servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt} (81%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorScreen.kt => servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt} (87%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorViewModel.kt => servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt} (67%) create mode 100644 feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt delete mode 100644 feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryCertificateErrorRepository.kt diff --git a/feature/account/servercertificate/build.gradle.kts b/feature/account/servercertificate/build.gradle.kts new file mode 100644 index 0000000000..ac04d5f407 --- /dev/null +++ b/feature/account/servercertificate/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + id(ThunderbirdPlugins.Library.androidCompose) +} + +android { + namespace = "app.k9mail.feature.account.servercertificate" + resourcePrefix = "account_servercertificate_" +} + +dependencies { + implementation(projects.core.ui.compose.designsystem) + implementation(projects.core.common) + implementation(projects.feature.account.common) + + implementation(projects.mail.common) + + testImplementation(projects.core.ui.compose.testing) +} diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt new file mode 100644 index 0000000000..94de6d5e3a --- /dev/null +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt @@ -0,0 +1,29 @@ +package app.k9mail.feature.account.servercertificate + +import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract +import app.k9mail.feature.account.servercertificate.domain.usecase.AddServerCertificateException +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorViewModel +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.core.module.Module +import org.koin.dsl.module + +val featureAccountServerCertificateModule: Module = module { + + single { + InMemoryServerCertificateErrorRepository() + } + + factory { + AddServerCertificateException( + localKeyStore = get(), + ) + } + + viewModel { + AccountServerCertificateErrorViewModel( + certificateErrorRepository = get(), + addServerCertificateException = get(), + ) + } +} diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt new file mode 100644 index 0000000000..61a2786ee8 --- /dev/null +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt @@ -0,0 +1,21 @@ +package app.k9mail.feature.account.servercertificate.data + +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract +import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError + +class InMemoryServerCertificateErrorRepository( + private var serverCertificateError: ServerCertificateError? = null, +) : AccountServerCertificateDomainContract.ServerCertificateErrorRepository { + + override fun getCertificateError(): ServerCertificateError? { + return serverCertificateError + } + + override fun setCertificateError(serverCertificateError: ServerCertificateError) { + this.serverCertificateError = serverCertificateError + } + + override fun clearCertificateError() { + serverCertificateError = null + } +} diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt new file mode 100644 index 0000000000..dd5d8e8ee5 --- /dev/null +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt @@ -0,0 +1,21 @@ +package app.k9mail.feature.account.servercertificate.domain + +import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError +import java.security.cert.X509Certificate + +interface AccountServerCertificateDomainContract { + + interface ServerCertificateErrorRepository { + fun getCertificateError(): ServerCertificateError? + + fun setCertificateError(serverCertificateError: ServerCertificateError) + + fun clearCertificateError() + } + + interface UseCase { + fun interface AddServerCertificateException { + suspend fun addCertificate(hostname: String, port: Int, certificate: X509Certificate?) + } + } +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/CertificateError.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt similarity index 57% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/CertificateError.kt rename to feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt index d85b7a0052..796b6d41a7 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/CertificateError.kt +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.servercertificate.domain.entity import java.security.cert.X509Certificate -data class CertificateError( +data class ServerCertificateError( val hostname: String, val port: Int, val certificateChain: List, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/AddServerCertificateException.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/usecase/AddServerCertificateException.kt similarity index 73% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/AddServerCertificateException.kt rename to feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/usecase/AddServerCertificateException.kt index a1cfb8cf29..baf3c3d4fe 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/AddServerCertificateException.kt +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/usecase/AddServerCertificateException.kt @@ -1,6 +1,6 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.servercertificate.domain.usecase -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract.UseCase import com.fsck.k9.mail.ssl.LocalKeyStore import java.security.cert.X509Certificate import kotlinx.coroutines.CoroutineDispatcher @@ -10,7 +10,7 @@ import kotlinx.coroutines.withContext internal class AddServerCertificateException( private val localKeyStore: LocalKeyStore, private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO, -) : DomainContract.UseCase.AddServerCertificateException { +) : UseCase.AddServerCertificateException { override suspend fun addCertificate(hostname: String, port: Int, certificate: X509Certificate?) { withContext(coroutineDispatcher) { localKeyStore.addCertificate(hostname, port, certificate) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorContract.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt similarity index 81% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorContract.kt rename to feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt index 18ffe42a7f..e5f21ab86d 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorContract.kt +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.setup.ui.servercertificate +package app.k9mail.feature.account.servercertificate.ui import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel -interface CertificateErrorContract { +interface AccountServerCertificateErrorContract { interface ViewModel : UnidirectionalViewModel diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorScreen.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt similarity index 87% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorScreen.kt rename to feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt index f02b471a3b..7c0a4343a2 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorScreen.kt +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.servercertificate +package app.k9mail.feature.account.servercertificate.ui import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Column @@ -21,11 +21,11 @@ import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer import app.k9mail.core.ui.compose.designsystem.template.Scaffold import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.MainTheme -import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository -import app.k9mail.feature.account.setup.domain.entity.CertificateError -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.Effect -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.Event -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.ViewModel +import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository +import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Effect +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Event +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.ViewModel import java.security.cert.CertificateFactory import java.security.cert.X509Certificate import org.koin.androidx.compose.koinViewModel @@ -33,11 +33,11 @@ import org.koin.androidx.compose.koinViewModel // Note: This is a placeholder with mostly hardcoded text. // TODO: Replace with final design. @Composable -internal fun CertificateErrorScreen( +fun CertificateErrorScreen( onCertificateAccepted: () -> Unit, onBack: () -> Unit, modifier: Modifier = Modifier, - viewModel: ViewModel = koinViewModel(), + viewModel: ViewModel = koinViewModel(), ) { val (state, dispatch) = viewModel.observe { effect -> when (effect) { @@ -138,7 +138,7 @@ internal fun CertificateErrorScreenK9Preview() { val certificateFactory = CertificateFactory.getInstance("X.509") val certificate = certificateFactory.generateCertificate(inputStream) as X509Certificate - val certificateError = CertificateError( + val serverCertificateError = ServerCertificateError( hostname = "mail.domain.example", port = 143, certificateChain = listOf(certificate), @@ -148,9 +148,9 @@ internal fun CertificateErrorScreenK9Preview() { CertificateErrorScreen( onCertificateAccepted = {}, onBack = {}, - viewModel = CertificateErrorViewModel( + viewModel = AccountServerCertificateErrorViewModel( addServerCertificateException = { _, _, _ -> }, - certificateErrorRepository = InMemoryCertificateErrorRepository(certificateError), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(serverCertificateError), ), ) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorViewModel.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt similarity index 67% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorViewModel.kt rename to feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt index 1edcde3322..58641a40b8 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/servercertificate/CertificateErrorViewModel.kt +++ b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt @@ -1,13 +1,13 @@ -package app.k9mail.feature.account.setup.ui.servercertificate +package app.k9mail.feature.account.servercertificate.ui import androidx.lifecycle.viewModelScope import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.setup.domain.DomainContract.CertificateErrorRepository -import app.k9mail.feature.account.setup.domain.DomainContract.UseCase.AddServerCertificateException -import app.k9mail.feature.account.setup.domain.entity.CertificateError -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.Effect -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.Event -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract.State +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract.UseCase +import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Effect +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Event +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.State import com.fsck.k9.logging.Timber import com.fsck.k9.mail.filter.Hex import java.security.MessageDigest @@ -15,15 +15,15 @@ import java.security.NoSuchAlgorithmException import java.security.cert.CertificateEncodingException import kotlinx.coroutines.launch -class CertificateErrorViewModel( - private val certificateErrorRepository: CertificateErrorRepository, - private val addServerCertificateException: AddServerCertificateException, +class AccountServerCertificateErrorViewModel( + private val certificateErrorRepository: AccountServerCertificateDomainContract.ServerCertificateErrorRepository, + private val addServerCertificateException: UseCase.AddServerCertificateException, initialState: State = State(), -) : BaseViewModel(initialState), CertificateErrorContract.ViewModel { - private val certificateError: CertificateError? = certificateErrorRepository.getCertificateError() +) : BaseViewModel(initialState), AccountServerCertificateErrorContract.ViewModel { + private val serverCertificateError: ServerCertificateError? = certificateErrorRepository.getCertificateError() init { - setErrorMessage(buildErrorMessage(certificateError)) + setErrorMessage(buildErrorMessage(serverCertificateError)) } override fun event(event: Event) { @@ -34,7 +34,7 @@ class CertificateErrorViewModel( } private fun acceptCertificate() { - val certificateError = requireNotNull(certificateError) + val certificateError = requireNotNull(serverCertificateError) viewModelScope.launch { addServerCertificateException.addCertificate( @@ -56,8 +56,8 @@ class CertificateErrorViewModel( emitEffect(Effect.NavigateCertificateAccepted) } - private fun buildErrorMessage(certificateError: CertificateError?): String { - val certificate = certificateError?.certificateChain?.firstOrNull() ?: return "" + private fun buildErrorMessage(serverCertificateError: ServerCertificateError?): String { + val certificate = serverCertificateError?.certificateChain?.firstOrNull() ?: return "" return buildString { certificate.subjectAlternativeNames?.let { subjectAlternativeNames -> diff --git a/feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt b/feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt new file mode 100644 index 0000000000..2009862fb9 --- /dev/null +++ b/feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt @@ -0,0 +1,35 @@ +package app.k9mail.feature.account.servercertificate + +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract +import com.fsck.k9.mail.ssl.LocalKeyStore +import org.junit.Test +import org.koin.core.annotation.KoinExperimentalAPI +import org.koin.core.module.Module +import org.koin.dsl.koinApplication +import org.koin.dsl.module +import org.koin.test.KoinTest +import org.koin.test.check.checkModules +import org.koin.test.verify.verify +import org.mockito.Mockito + +class AccountServerCertificateModuleKtTest : KoinTest { + + private val externalModule: Module = module { + single { Mockito.mock() } + } + + @OptIn(KoinExperimentalAPI::class) + @Test + fun `should have a valid di module`() { + featureAccountServerCertificateModule.verify( + extraTypes = listOf( + AccountServerCertificateErrorContract.State::class, + ), + ) + + koinApplication { + modules(externalModule, featureAccountServerCertificateModule) + checkModules() + } + } +} diff --git a/feature/account/setup/build.gradle.kts b/feature/account/setup/build.gradle.kts index 5509595281..a5a9c3dc75 100644 --- a/feature/account/setup/build.gradle.kts +++ b/feature/account/setup/build.gradle.kts @@ -19,14 +19,17 @@ android { dependencies { implementation(projects.core.ui.compose.designsystem) implementation(projects.core.common) + implementation(projects.mail.common) implementation(projects.mail.protocols.imap) implementation(projects.mail.protocols.pop3) implementation(projects.mail.protocols.smtp) implementation(projects.feature.autodiscovery.service) + api(projects.feature.account.common) implementation(projects.feature.account.oauth) + implementation(projects.feature.account.servercertificate) testImplementation(projects.core.ui.compose.testing) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt index e823a44711..d65b3e03dd 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt @@ -4,9 +4,8 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryService import app.k9mail.autodiscovery.service.RealAutoDiscoveryService import app.k9mail.feature.account.common.featureAccountCommonModule import app.k9mail.feature.account.oauth.featureAccountOAuthModule -import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository +import app.k9mail.feature.account.servercertificate.featureAccountServerCertificateModule import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.usecase.AddServerCertificateException import app.k9mail.feature.account.setup.domain.usecase.CreateAccount import app.k9mail.feature.account.setup.domain.usecase.GetAutoDiscovery import app.k9mail.feature.account.setup.domain.usecase.ValidateServerSettings @@ -23,7 +22,6 @@ import app.k9mail.feature.account.setup.ui.options.AccountOptionsViewModel import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigValidator import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigViewModel -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorViewModel import app.k9mail.feature.account.setup.ui.validation.AccountValidationViewModel import com.fsck.k9.mail.store.imap.ImapServerSettingsValidator import com.fsck.k9.mail.store.pop3.Pop3ServerSettingsValidator @@ -35,7 +33,7 @@ import org.koin.core.qualifier.named import org.koin.dsl.module val featureAccountSetupModule: Module = module { - includes(featureAccountCommonModule, featureAccountOAuthModule) + includes(featureAccountCommonModule, featureAccountOAuthModule, featureAccountServerCertificateModule) single { OkHttpClient() @@ -54,8 +52,6 @@ val featureAccountSetupModule: Module = module { ) } - single { InMemoryCertificateErrorRepository() } - factory { ValidateServerSettings( authStateStorage = get(), @@ -74,12 +70,6 @@ val featureAccountSetupModule: Module = module { ) } - factory { - AddServerCertificateException( - localKeyStore = get(), - ) - } - factory { CreateAccount( accountCreator = get(), @@ -143,12 +133,6 @@ val featureAccountSetupModule: Module = module { accountStateRepository = get(), ) } - viewModel { - CertificateErrorViewModel( - certificateErrorRepository = get(), - addServerCertificateException = get(), - ) - } } internal const val NAME_INCOMING_VALIDATION = "incoming_validation" diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryCertificateErrorRepository.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryCertificateErrorRepository.kt deleted file mode 100644 index 834ec8007d..0000000000 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/data/InMemoryCertificateErrorRepository.kt +++ /dev/null @@ -1,21 +0,0 @@ -package app.k9mail.feature.account.setup.data - -import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.CertificateError - -class InMemoryCertificateErrorRepository( - private var certificateError: CertificateError? = null, -) : DomainContract.CertificateErrorRepository { - - override fun getCertificateError(): CertificateError? { - return certificateError - } - - override fun setCertificateError(certificateError: CertificateError) { - this.certificateError = certificateError - } - - override fun clearCertificateError() { - certificateError = null - } -} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt index 0a77856e38..e22b349d33 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt @@ -3,21 +3,12 @@ package app.k9mail.feature.account.setup.domain import app.k9mail.autodiscovery.api.AutoDiscoveryResult import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.feature.account.common.domain.entity.AccountOptions -import app.k9mail.feature.account.setup.domain.entity.CertificateError import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.server.ServerSettingsValidationResult import java.security.cert.X509Certificate interface DomainContract { - interface CertificateErrorRepository { - fun getCertificateError(): CertificateError? - - fun setCertificateError(certificateError: CertificateError) - - fun clearCertificateError() - } - interface UseCase { fun interface GetAutoDiscovery { suspend fun execute(emailAddress: String): AutoDiscoveryResult diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt index b497174085..f51f997ba5 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt @@ -13,8 +13,8 @@ import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.WizardNavigationBarState import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.oauth.ui.preview.PreviewAccountOAuthViewModel +import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.ViewModel import com.fsck.k9.mail.server.ServerSettingsValidationResult @@ -65,7 +65,7 @@ internal fun AccountIncomingValidationScreenK9Preview() { }, accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), isIncomingValidation = true, ), @@ -84,7 +84,7 @@ internal fun AccountIncomingValidationScreenThunderbirdPreview() { }, accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), isIncomingValidation = true, ), @@ -103,7 +103,7 @@ internal fun AccountOutgoingValidationScreenK9Preview() { }, accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), isIncomingValidation = false, ), @@ -122,7 +122,7 @@ internal fun AccountOutgoingValidationScreenThunderbirdPreview() { }, accountStateRepository = PreviewAccountStateRepository(), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = PreviewAccountOAuthViewModel(), isIncomingValidation = false, ), diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt index 5cdd6d5d40..634513bbbf 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt @@ -5,7 +5,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import app.k9mail.core.ui.compose.common.mvi.observe -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorScreen +import app.k9mail.feature.account.servercertificate.ui.CertificateErrorScreen import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.ViewModel diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt index c7003ac4bf..dbf83ee224 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt @@ -6,8 +6,9 @@ import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract +import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.CertificateError import app.k9mail.feature.account.setup.domain.entity.isOAuth import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Error @@ -25,7 +26,7 @@ internal class AccountValidationViewModel( private val validateServerSettings: DomainContract.UseCase.ValidateServerSettings, private val accountStateRepository: AccountDomainContract.AccountStateRepository, private val authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, - private val certificateErrorRepository: DomainContract.CertificateErrorRepository, + private val certificateErrorRepository: AccountServerCertificateDomainContract.ServerCertificateErrorRepository, override val oAuthViewModel: AccountOAuthContract.ViewModel, override val isIncomingValidation: Boolean = true, initialState: State? = null, @@ -169,7 +170,7 @@ internal class AccountValidationViewModel( val serverSettings = checkNotNull(state.value.serverSettings) certificateErrorRepository.setCertificateError( - CertificateError( + ServerCertificateError( hostname = serverSettings.host!!, port = serverSettings.port, certificateChain = error.certificateChain, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index 05d3546bdc..4d7f20acde 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -4,6 +4,7 @@ import android.content.Context import app.k9mail.core.common.oauth.OAuthConfigurationFactory import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult import app.k9mail.feature.account.setup.ui.AccountSetupContract @@ -11,7 +12,6 @@ import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryCon import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract -import app.k9mail.feature.account.setup.ui.servercertificate.CertificateErrorContract import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract import com.fsck.k9.mail.oauth.AuthStateStorage import com.fsck.k9.mail.oauth.OAuth2TokenProvider @@ -69,7 +69,7 @@ class AccountSetupModuleKtTest : KoinTest { AccountOutgoingConfigContract.State::class, AccountOptionsContract.State::class, AccountState::class, - CertificateErrorContract.State::class, + AccountServerCertificateErrorContract.State::class, AuthStateStorage::class, Context::class, Boolean::class, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt index 10ae448644..91fdfe08ab 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt @@ -5,7 +5,7 @@ import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.entity.AccountState -import app.k9mail.feature.account.setup.data.InMemoryCertificateErrorRepository +import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository import app.k9mail.feature.account.setup.ui.FakeAccountOAuthViewModel import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Error @@ -199,7 +199,7 @@ class AccountValidationViewModelTest { }, accountStateRepository = InMemoryAccountStateRepository(), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = FakeAccountOAuthViewModel(), initialState = initialState, ) @@ -238,7 +238,7 @@ class AccountValidationViewModelTest { }, accountStateRepository = InMemoryAccountStateRepository(accountState), authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryCertificateErrorRepository(), + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = FakeAccountOAuthViewModel(), initialState = initialState, ) diff --git a/settings.gradle.kts b/settings.gradle.kts index 3fdff2363d..6e63d46624 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -46,6 +46,7 @@ include( include( ":feature:account:common", ":feature:account:oauth", + ":feature:account:servercertificate", ":feature:account:setup", ) -- GitLab From 51fb16500332747aad3a6e2a70a4b95d8f5f56f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Fri, 1 Sep 2023 12:37:23 +0200 Subject: [PATCH 11/94] Remove ServerSettingsExtension as it's already part of the OAuth module --- .../account/setup/domain/entity/ServerSettingsExtension.kt | 6 ------ .../setup/ui/validation/AccountValidationViewModel.kt | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ServerSettingsExtension.kt diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ServerSettingsExtension.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ServerSettingsExtension.kt deleted file mode 100644 index cc4425d19c..0000000000 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ServerSettingsExtension.kt +++ /dev/null @@ -1,6 +0,0 @@ -package app.k9mail.feature.account.setup.domain.entity - -import com.fsck.k9.mail.AuthType -import com.fsck.k9.mail.ServerSettings - -fun ServerSettings?.isOAuth() = this?.authenticationType == AuthType.XOAUTH2 diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt index dbf83ee224..b42acf6789 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt @@ -5,11 +5,11 @@ import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract import app.k9mail.feature.account.oauth.domain.entity.OAuthResult +import app.k9mail.feature.account.oauth.domain.entity.isOAuth import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.domain.entity.isOAuth import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Error import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event -- GitLab From ea241adb7b3457ffda6bb1924c35871e7cc6e334 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 14:29:55 +0000 Subject: [PATCH 12/94] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/android.yml | 4 ++-- .github/workflows/codeql.yml | 2 +- .github/workflows/gradle-cache.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 6c060792b2..d3e2769cd2 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -16,13 +16,13 @@ jobs: validation: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: gradle/wrapper-validation-action@v1 build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: temurin diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f9f570c0c3..becf6b92d6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -16,7 +16,7 @@ jobs: security-events: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: diff --git a/.github/workflows/gradle-cache.yml b/.github/workflows/gradle-cache.yml index 0e4b6f3d72..0f2d4c2334 100644 --- a/.github/workflows/gradle-cache.yml +++ b/.github/workflows/gradle-cache.yml @@ -18,7 +18,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: temurin -- GitLab From 6acdf48e2d469b1cb46fa44ea7176dbc4e5d768d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Fri, 1 Sep 2023 12:57:32 +0200 Subject: [PATCH 13/94] Add account server validation module --- .../com/fsck/k9/DependencyInjectionTest.kt | 12 ++-- .../account/common/ui/AppTitleTopHeader.kt | 6 +- .../account/common/ui/WizardNavigationBar.kt | 6 +- .../common/src/main/res/values/strings.xml | 6 ++ .../ui/fake}/FakeAccountOAuthViewModel.kt | 2 +- .../server/validation/build.gradle.kts | 33 +++++++++ .../validation/ServerValidationModule.kt | 67 ++++++++++++++++++ .../domain/ServerValidationDomainContract.kt | 14 ++++ .../domain/usecase/ValidateServerSettings.kt | 8 +-- .../validation/ui/ServerValidationContent.kt} | 32 ++++----- .../ui/ServerValidationContract.kt} | 4 +- .../ui/ServerValidationMainScreen.kt} | 36 +++++----- .../validation/ui/ServerValidationScreen.kt} | 14 ++-- .../ui/ServerValidationStateMapper.kt} | 6 +- .../ui/ServerValidationStringMapper.kt | 29 ++++++++ .../ui/ServerValidationViewModel.kt} | 22 +++--- .../ui/fake/FakeServerValidationViewModel.kt} | 14 ++-- .../src/main/res/values/strings.xml | 15 ++++ .../ServerValidationModuleKtTest.kt | 69 +++++++++++++++++++ .../domain/usecase/FakeAuthStateStorage.kt | 13 ++++ .../usecase/ValidateServerSettingsTest.kt | 5 +- .../ui/ServerValidationScreenKtTest.kt} | 13 ++-- .../ui/ServerValidationStateTest.kt} | 6 +- .../ui/ServerValidationViewModelTest.kt} | 20 +++--- feature/account/setup/build.gradle.kts | 1 + .../account/setup/AccountSetupModule.kt | 57 +++------------ .../account/setup/domain/DomainContract.kt | 5 -- .../account/setup/ui/AccountSetupScreen.kt | 22 +++--- .../AccountIncomingConfigStateMapper.kt | 8 --- .../AccountOutgoingConfigStateMapper.kt | 8 --- .../AccountValidationStringMapper.kt | 29 -------- .../ui/validation/InMemoryAuthStateStorage.kt | 17 ----- .../setup/src/main/res/values/strings.xml | 13 ---- .../account/setup/AccountSetupModuleKtTest.kt | 4 +- .../setup/ui/AccountSetupScreenKtTest.kt | 10 +-- .../AccountAutoDiscoveryViewModelTest.kt | 2 +- .../FakeAccountAutoDiscoveryViewModel.kt | 2 +- settings.gradle.kts | 1 + 38 files changed, 380 insertions(+), 251 deletions(-) create mode 100644 feature/account/common/src/main/res/values/strings.xml rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup/ui => oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/fake}/FakeAccountOAuthViewModel.kt (93%) create mode 100644 feature/account/server/validation/build.gradle.kts create mode 100644 feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt create mode 100644 feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/domain/ServerValidationDomainContract.kt rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation}/domain/usecase/ValidateServerSettings.kt (82%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContent.kt => server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContent.kt} (81%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContract.kt => server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContract.kt} (94%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt => server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt} (79%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt => server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreen.kt} (74%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateMapper.kt => server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStateMapper.kt} (57%) create mode 100644 feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStringMapper.kt rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt => server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt} (90%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/FakeAccountValidationViewModel.kt => server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeServerValidationViewModel.kt} (60%) create mode 100644 feature/account/server/validation/src/main/res/values/strings.xml create mode 100644 feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt create mode 100644 feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/domain/usecase/FakeAuthStateStorage.kt rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation}/domain/usecase/ValidateServerSettingsTest.kt (96%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreenKtTest.kt => server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreenKtTest.kt} (71%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateTest.kt => server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStateTest.kt} (72%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt => server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt} (94%) delete mode 100644 feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStringMapper.kt delete mode 100644 feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/InMemoryAuthStateStorage.kt diff --git a/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt b/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt index 636d824ab0..f3cbf1e39c 100644 --- a/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt +++ b/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt @@ -3,8 +3,10 @@ package com.fsck.k9 import android.view.ContextThemeWrapper import androidx.lifecycle.LifecycleOwner import androidx.work.WorkerParameters -import app.k9mail.feature.account.setup.domain.DomainContract.UseCase.ValidateServerSettings -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract +import app.k9mail.feature.account.server.validation.KOIN_NAME_INCOMING_SERVER_VALIDATION +import app.k9mail.feature.account.server.validation.KOIN_NAME_OUTGOING_SERVER_VALIDATION +import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract import com.fsck.k9.account.AccountRemoverWorker import com.fsck.k9.job.MailSyncWorker import com.fsck.k9.mail.oauth.AuthStateStorage @@ -59,9 +61,9 @@ class DependencyInjectionTest : AutoCloseKoinTest() { withParameters(clazz = Class.forName("com.fsck.k9.view.K9WebViewClient").kotlin) { parametersOf(null, null) } - withParameter(named("incoming_validation")) { authStateStorage } - withParameter(named("outgoing_validation")) { authStateStorage } - withParameter { authStateStorage } + withParameter(named(KOIN_NAME_INCOMING_SERVER_VALIDATION)) { authStateStorage } + withParameter(named(KOIN_NAME_OUTGOING_SERVER_VALIDATION)) { authStateStorage } + withParameter { authStateStorage } withParameter { mock() } } } diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/AppTitleTopHeader.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/AppTitleTopHeader.kt index 13fde1bf9d..ad0818602d 100644 --- a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/AppTitleTopHeader.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/AppTitleTopHeader.kt @@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight @@ -18,11 +19,12 @@ import app.k9mail.core.ui.compose.designsystem.atom.text.TextHeadline2 import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer import app.k9mail.core.ui.compose.theme.MainTheme import app.k9mail.core.ui.compose.theme.PreviewWithThemes +import app.k9mail.feature.account.common.R @Composable fun AppTitleTopHeader( - title: String, modifier: Modifier = Modifier, + title: String = stringResource(id = R.string.account_common_title), ) { ResponsiveWidthContainer( modifier = Modifier @@ -64,6 +66,6 @@ fun AppTitleTopHeader( @Composable internal fun AppTitleTopHeaderPreview() { PreviewWithThemes { - AppTitleTopHeader("Title") + AppTitleTopHeader(title = "Title") } } diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/WizardNavigationBar.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/WizardNavigationBar.kt index f2e625d254..fb5d1fd7c9 100644 --- a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/WizardNavigationBar.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/WizardNavigationBar.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import app.k9mail.core.ui.compose.common.DevicePreviews import app.k9mail.core.ui.compose.designsystem.atom.button.Button import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonOutlined @@ -13,14 +14,15 @@ import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.MainTheme import app.k9mail.core.ui.compose.theme.PreviewWithThemes +import app.k9mail.feature.account.common.R @Composable fun WizardNavigationBar( - nextButtonText: String, - backButtonText: String, onNextClick: () -> Unit, onBackClick: () -> Unit, modifier: Modifier = Modifier, + nextButtonText: String = stringResource(id = R.string.account_common_button_next), + backButtonText: String = stringResource(id = R.string.account_common_button_back), state: WizardNavigationBarState = WizardNavigationBarState(), ) { ResponsiveWidthContainer( diff --git a/feature/account/common/src/main/res/values/strings.xml b/feature/account/common/src/main/res/values/strings.xml new file mode 100644 index 0000000000..ecff2a1a32 --- /dev/null +++ b/feature/account/common/src/main/res/values/strings.xml @@ -0,0 +1,6 @@ + + + K-9 Mail + Next + Back + diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/FakeAccountOAuthViewModel.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/fake/FakeAccountOAuthViewModel.kt similarity index 93% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/FakeAccountOAuthViewModel.kt rename to feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/fake/FakeAccountOAuthViewModel.kt index d76087a2ac..01f2ddb578 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/FakeAccountOAuthViewModel.kt +++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/ui/fake/FakeAccountOAuthViewModel.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui +package app.k9mail.feature.account.oauth.ui.fake import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.oauth.ui.AccountOAuthContract.Effect diff --git a/feature/account/server/validation/build.gradle.kts b/feature/account/server/validation/build.gradle.kts new file mode 100644 index 0000000000..aa23f22b6b --- /dev/null +++ b/feature/account/server/validation/build.gradle.kts @@ -0,0 +1,33 @@ +plugins { + id(ThunderbirdPlugins.Library.androidCompose) +} + +android { + namespace = "app.k9mail.feature.account.server.validation" + resourcePrefix = "account_server_validation_" + + buildTypes { + debug { + manifestPlaceholders["appAuthRedirectScheme"] = "FIXME: override this in your app project" + } + release { + manifestPlaceholders["appAuthRedirectScheme"] = "FIXME: override this in your app project" + } + } +} + +dependencies { + implementation(projects.core.ui.compose.designsystem) + implementation(projects.core.common) + + implementation(projects.mail.common) + implementation(projects.mail.protocols.imap) + implementation(projects.mail.protocols.pop3) + implementation(projects.mail.protocols.smtp) + + implementation(projects.feature.account.common) + implementation(projects.feature.account.oauth) + implementation(projects.feature.account.servercertificate) + + testImplementation(projects.core.ui.compose.testing) +} diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt new file mode 100644 index 0000000000..3fe94c8b25 --- /dev/null +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt @@ -0,0 +1,67 @@ +package app.k9mail.feature.account.server.validation + +import app.k9mail.core.common.coreCommonModule +import app.k9mail.feature.account.common.featureAccountCommonModule +import app.k9mail.feature.account.oauth.featureAccountOAuthModule +import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract +import app.k9mail.feature.account.server.validation.domain.usecase.ValidateServerSettings +import app.k9mail.feature.account.server.validation.ui.ServerValidationViewModel +import app.k9mail.feature.account.servercertificate.featureAccountServerCertificateModule +import com.fsck.k9.mail.store.imap.ImapServerSettingsValidator +import com.fsck.k9.mail.store.pop3.Pop3ServerSettingsValidator +import com.fsck.k9.mail.transport.smtp.SmtpServerSettingsValidator +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.core.qualifier.named +import org.koin.dsl.module + +val featureAccountServerValidationModule = module { + includes( + coreCommonModule, + featureAccountCommonModule, + featureAccountServerCertificateModule, + featureAccountOAuthModule, + ) + + factory { + ValidateServerSettings( + authStateStorage = get(), + imapValidator = ImapServerSettingsValidator( + trustedSocketFactory = get(), + oAuth2TokenProviderFactory = get(), + clientIdAppName = "null", // TODO get real value + ), + pop3Validator = Pop3ServerSettingsValidator( + trustedSocketFactory = get(), + ), + smtpValidator = SmtpServerSettingsValidator( + trustedSocketFactory = get(), + oAuth2TokenProviderFactory = get(), + ), + ) + } + + viewModel(named(KOIN_NAME_INCOMING_SERVER_VALIDATION)) { + ServerValidationViewModel( + validateServerSettings = get(), + accountStateRepository = get(), + authorizationStateRepository = get(), + certificateErrorRepository = get(), + oAuthViewModel = get(), + isIncomingValidation = true, + ) + } + + viewModel(named(KOIN_NAME_OUTGOING_SERVER_VALIDATION)) { + ServerValidationViewModel( + validateServerSettings = get(), + accountStateRepository = get(), + authorizationStateRepository = get(), + certificateErrorRepository = get(), + oAuthViewModel = get(), + isIncomingValidation = false, + ) + } +} + +const val KOIN_NAME_INCOMING_SERVER_VALIDATION = "incoming_server_validation" +const val KOIN_NAME_OUTGOING_SERVER_VALIDATION = "outgoing_server_validation" diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/domain/ServerValidationDomainContract.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/domain/ServerValidationDomainContract.kt new file mode 100644 index 0000000000..7ee70de5cb --- /dev/null +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/domain/ServerValidationDomainContract.kt @@ -0,0 +1,14 @@ +package app.k9mail.feature.account.server.validation.domain + +import com.fsck.k9.mail.ServerSettings +import com.fsck.k9.mail.server.ServerSettingsValidationResult + +interface ServerValidationDomainContract { + + interface UseCase { + + fun interface ValidateServerSettings { + suspend fun execute(settings: ServerSettings): ServerSettingsValidationResult + } + } +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServerSettings.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/domain/usecase/ValidateServerSettings.kt similarity index 82% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServerSettings.kt rename to feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/domain/usecase/ValidateServerSettings.kt index 0d5a8f4ccd..f96d2ba087 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServerSettings.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/domain/usecase/ValidateServerSettings.kt @@ -1,6 +1,6 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.validation.domain.usecase -import app.k9mail.feature.account.setup.domain.DomainContract.UseCase +import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.oauth.AuthStateStorage import com.fsck.k9.mail.server.ServerSettingsValidationResult @@ -9,13 +9,13 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -internal class ValidateServerSettings( +class ValidateServerSettings( private val authStateStorage: AuthStateStorage, private val imapValidator: ServerSettingsValidator, private val pop3Validator: ServerSettingsValidator, private val smtpValidator: ServerSettingsValidator, private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO, -) : UseCase.ValidateServerSettings { +) : ServerValidationDomainContract.UseCase.ValidateServerSettings { override suspend fun execute(settings: ServerSettings): ServerSettingsValidationResult { return withContext(coroutineDispatcher) { when (settings.type) { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContent.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContent.kt similarity index 81% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContent.kt rename to feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContent.kt index c380abafc1..ba7b942d4d 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContent.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContent.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.validation +package app.k9mail.feature.account.server.validation.ui import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -27,13 +27,13 @@ import app.k9mail.feature.account.common.ui.item.SuccessItem import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.oauth.ui.AccountOAuthView import app.k9mail.feature.account.oauth.ui.preview.PreviewAccountOAuthViewModel -import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.State +import app.k9mail.feature.account.server.validation.R +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State @Suppress("LongMethod") @Composable -internal fun AccountValidationContent( +internal fun ServerValidationContent( state: State, isIncomingValidation: Boolean, oAuthViewModel: AccountOAuthContract.ViewModel, @@ -63,9 +63,9 @@ internal fun AccountValidationContent( ErrorItem( title = stringResource( id = if (isIncomingValidation) { - R.string.account_setup_settings_validation_incoming_loading_error + R.string.account_server_validation_incoming_loading_error } else { - R.string.account_setup_settings_validation_outgoing_loading_error + R.string.account_server_validation_outgoing_loading_error }, ), message = state.error.toResourceString(resources), @@ -77,9 +77,9 @@ internal fun AccountValidationContent( SuccessItem( message = stringResource( id = if (isIncomingValidation) { - R.string.account_setup_settings_validation_incoming_success + R.string.account_server_validation_incoming_success } else { - R.string.account_setup_settings_validation_outgoing_success + R.string.account_server_validation_outgoing_success }, ), ) @@ -94,7 +94,7 @@ internal fun AccountValidationContent( ) { TextSubtitle1( text = stringResource( - id = R.string.account_setup_settings_validation_sign_in, + id = R.string.account_server_validation_sign_in, ), ) Spacer(modifier = Modifier.padding(MainTheme.spacings.default)) @@ -110,9 +110,9 @@ internal fun AccountValidationContent( LoadingItem( message = stringResource( id = if (isIncomingValidation) { - R.string.account_setup_settings_validation_incoming_loading_message + R.string.account_server_validation_incoming_loading_message } else { - R.string.account_setup_settings_validation_outgoing_loading_message + R.string.account_server_validation_outgoing_loading_message }, ), ) @@ -124,9 +124,9 @@ internal fun AccountValidationContent( @Composable @DevicePreviews -internal fun AccountIncomingValidationContentPreview() { +internal fun IncomingServerValidationContentPreview() { PreviewWithThemes { - AccountValidationContent( + ServerValidationContent( onEvent = { }, state = State(), isIncomingValidation = true, @@ -138,9 +138,9 @@ internal fun AccountIncomingValidationContentPreview() { @Composable @DevicePreviews -internal fun AccountOutgoingValidationContentPreview() { +internal fun OutgoingServerValidationContentPreview() { PreviewWithThemes { - AccountValidationContent( + ServerValidationContent( onEvent = { }, state = State(), isIncomingValidation = false, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContract.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContract.kt similarity index 94% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContract.kt rename to feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContract.kt index 47e382bb19..083f4a606e 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationContract.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContract.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.validation +package app.k9mail.feature.account.server.validation.ui import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel import app.k9mail.feature.account.oauth.domain.entity.OAuthResult @@ -7,7 +7,7 @@ import com.fsck.k9.mail.ServerSettings import java.io.IOException import java.security.cert.X509Certificate -interface AccountValidationContract { +interface ServerValidationContract { interface ViewModel : UnidirectionalViewModel { val isIncomingValidation: Boolean diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt similarity index 79% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt rename to feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt index f51f997ba5..0e34bad7e0 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationMainScreen.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt @@ -1,8 +1,7 @@ -package app.k9mail.feature.account.setup.ui.validation +package app.k9mail.feature.account.server.validation.ui import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import app.k9mail.core.ui.compose.common.DevicePreviews import app.k9mail.core.ui.compose.designsystem.template.Scaffold @@ -13,14 +12,13 @@ import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.WizardNavigationBarState import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.oauth.ui.preview.PreviewAccountOAuthViewModel +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.ViewModel import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository -import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.ViewModel import com.fsck.k9.mail.server.ServerSettingsValidationResult @Composable -internal fun AccountValidationMainScreen( +internal fun ServerValidationMainScreen( viewModel: ViewModel, modifier: Modifier = Modifier, ) { @@ -29,12 +27,10 @@ internal fun AccountValidationMainScreen( Scaffold( topBar = { - AppTitleTopHeader(title = stringResource(id = R.string.account_setup_title)) + AppTitleTopHeader() }, bottomBar = { WizardNavigationBar( - nextButtonText = "", - backButtonText = stringResource(id = R.string.account_setup_button_back), onNextClick = {}, onBackClick = { dispatch(Event.OnBackClicked) }, state = WizardNavigationBarState( @@ -44,7 +40,7 @@ internal fun AccountValidationMainScreen( }, modifier = modifier, ) { innerPadding -> - AccountValidationContent( + ServerValidationContent( onEvent = { dispatch(it) }, state = state.value, isIncomingValidation = viewModel.isIncomingValidation, @@ -56,10 +52,10 @@ internal fun AccountValidationMainScreen( @Composable @DevicePreviews -internal fun AccountIncomingValidationScreenK9Preview() { +internal fun IncomingServerValidationScreenK9Preview() { K9Theme { - AccountValidationMainScreen( - viewModel = AccountValidationViewModel( + ServerValidationMainScreen( + viewModel = ServerValidationViewModel( validateServerSettings = { ServerSettingsValidationResult.Success }, @@ -75,10 +71,10 @@ internal fun AccountIncomingValidationScreenK9Preview() { @Composable @DevicePreviews -internal fun AccountIncomingValidationScreenThunderbirdPreview() { +internal fun IncomingServerValidationScreenThunderbirdPreview() { ThunderbirdTheme { - AccountValidationMainScreen( - viewModel = AccountValidationViewModel( + ServerValidationMainScreen( + viewModel = ServerValidationViewModel( validateServerSettings = { ServerSettingsValidationResult.Success }, @@ -96,8 +92,8 @@ internal fun AccountIncomingValidationScreenThunderbirdPreview() { @DevicePreviews internal fun AccountOutgoingValidationScreenK9Preview() { K9Theme { - AccountValidationMainScreen( - viewModel = AccountValidationViewModel( + ServerValidationMainScreen( + viewModel = ServerValidationViewModel( validateServerSettings = { ServerSettingsValidationResult.Success }, @@ -115,8 +111,8 @@ internal fun AccountOutgoingValidationScreenK9Preview() { @DevicePreviews internal fun AccountOutgoingValidationScreenThunderbirdPreview() { ThunderbirdTheme { - AccountValidationMainScreen( - viewModel = AccountValidationViewModel( + ServerValidationMainScreen( + viewModel = ServerValidationViewModel( validateServerSettings = { ServerSettingsValidationResult.Success }, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreen.kt similarity index 74% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt rename to feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreen.kt index 634513bbbf..5e79d0854e 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreen.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreen.kt @@ -1,17 +1,17 @@ -package app.k9mail.feature.account.setup.ui.validation +package app.k9mail.feature.account.server.validation.ui import androidx.activity.compose.BackHandler import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import app.k9mail.core.ui.compose.common.mvi.observe +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.ViewModel import app.k9mail.feature.account.servercertificate.ui.CertificateErrorScreen -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.ViewModel @Composable -internal fun AccountValidationScreen( +fun ServerValidationScreen( onNext: () -> Unit, onBack: () -> Unit, viewModel: ViewModel, @@ -32,14 +32,14 @@ internal fun AccountValidationScreen( dispatch(Event.OnBackClicked) } - if (state.value.error is AccountValidationContract.Error.CertificateError) { + if (state.value.error is ServerValidationContract.Error.CertificateError) { CertificateErrorScreen( onCertificateAccepted = { dispatch(Event.OnCertificateAccepted) }, onBack = { dispatch(Event.OnBackClicked) }, modifier = modifier, ) } else { - AccountValidationMainScreen( + ServerValidationMainScreen( viewModel = viewModel, modifier = modifier, ) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateMapper.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStateMapper.kt similarity index 57% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateMapper.kt rename to feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStateMapper.kt index 8a33ed30b4..b140ae2646 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateMapper.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStateMapper.kt @@ -1,9 +1,9 @@ -package app.k9mail.feature.account.setup.ui.validation +package app.k9mail.feature.account.server.validation.ui import app.k9mail.feature.account.common.domain.entity.AccountState -internal fun AccountState.toValidationState(isIncomingValidation: Boolean): AccountValidationContract.State { - return AccountValidationContract.State( +internal fun AccountState.toServerValidationState(isIncomingValidation: Boolean): ServerValidationContract.State { + return ServerValidationContract.State( emailAddress = emailAddress, serverSettings = if (isIncomingValidation) incomingServerSettings else outgoingServerSettings, isLoading = false, diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStringMapper.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStringMapper.kt new file mode 100644 index 0000000000..228e1d9fa1 --- /dev/null +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStringMapper.kt @@ -0,0 +1,29 @@ +package app.k9mail.feature.account.server.validation.ui + +import android.content.res.Resources +import app.k9mail.feature.account.server.validation.R +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Error + +internal fun Error.toResourceString(resources: Resources): String { + return when (this) { + is Error.AuthenticationError -> resources.getString( + R.string.account_server_validation_error_authentication, + ) + + is Error.CertificateError -> resources.getString( + R.string.account_server_validation_error_certificate, + ) + + is Error.NetworkError -> resources.getString( + R.string.account_server_validation_error_network, + ) + + is Error.ServerError -> resources.getString( + R.string.account_server_validation_error_server, + ) + + is Error.UnknownError -> resources.getString( + R.string.account_server_validation_error_unknown, + ) + } +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt similarity index 90% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt rename to feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt index b42acf6789..15653a7c4e 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModel.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.validation +package app.k9mail.feature.account.server.validation.ui import androidx.lifecycle.viewModelScope import app.k9mail.core.ui.compose.common.mvi.BaseViewModel @@ -7,13 +7,13 @@ import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.domain.entity.isOAuth import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Error +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError -import app.k9mail.feature.account.setup.domain.DomainContract -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Error -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.State import com.fsck.k9.mail.server.ServerSettingsValidationResult import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.delay @@ -22,18 +22,18 @@ import kotlinx.coroutines.launch private const val CONTINUE_NEXT_DELAY = 2000L @Suppress("TooManyFunctions") -internal class AccountValidationViewModel( - private val validateServerSettings: DomainContract.UseCase.ValidateServerSettings, +class ServerValidationViewModel( private val accountStateRepository: AccountDomainContract.AccountStateRepository, + private val validateServerSettings: ServerValidationDomainContract.UseCase.ValidateServerSettings, private val authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, private val certificateErrorRepository: AccountServerCertificateDomainContract.ServerCertificateErrorRepository, override val oAuthViewModel: AccountOAuthContract.ViewModel, override val isIncomingValidation: Boolean = true, initialState: State? = null, ) : BaseViewModel( - initialState = initialState ?: accountStateRepository.getState().toValidationState(isIncomingValidation), + initialState = initialState ?: accountStateRepository.getState().toServerValidationState(isIncomingValidation), ), - AccountValidationContract.ViewModel { + ServerValidationContract.ViewModel { override fun event(event: Event) { when (event) { @@ -49,7 +49,7 @@ internal class AccountValidationViewModel( private fun loadAccountStateAndValidate() { updateState { - accountStateRepository.getState().toValidationState(isIncomingValidation) + accountStateRepository.getState().toServerValidationState(isIncomingValidation) } onValidateConfig() } diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/FakeAccountValidationViewModel.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeServerValidationViewModel.kt similarity index 60% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/FakeAccountValidationViewModel.kt rename to feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeServerValidationViewModel.kt index 41840998e4..d0bc2cf010 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/FakeAccountValidationViewModel.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeServerValidationViewModel.kt @@ -1,14 +1,14 @@ -package app.k9mail.feature.account.setup.ui.validation +package app.k9mail.feature.account.server.validation.ui.fake import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.oauth.ui.AccountOAuthContract -import app.k9mail.feature.account.setup.ui.FakeAccountOAuthViewModel -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.State -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.ViewModel +import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.ViewModel -class FakeAccountValidationViewModel( +class FakeServerValidationViewModel( override val oAuthViewModel: AccountOAuthContract.ViewModel = FakeAccountOAuthViewModel(), override val isIncomingValidation: Boolean = true, initialState: State = State(), diff --git a/feature/account/server/validation/src/main/res/values/strings.xml b/feature/account/server/validation/src/main/res/values/strings.xml new file mode 100644 index 0000000000..603ba06d16 --- /dev/null +++ b/feature/account/server/validation/src/main/res/values/strings.xml @@ -0,0 +1,15 @@ + + + Authentication error + Certificate error + Network error + Server error + Unknown error + Checking incoming server settings… + Checking incoming server settings failed! + Incoming server settings are valid! + Checking outgoing server settings… + Checking outgoing server settings failed! + Outgoing server settings are valid! + Please sign in + diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt new file mode 100644 index 0000000000..a7444692b5 --- /dev/null +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt @@ -0,0 +1,69 @@ +package app.k9mail.feature.account.server.validation + +import android.content.Context +import app.k9mail.core.common.oauth.OAuthConfigurationFactory +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract +import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract +import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract +import com.fsck.k9.mail.oauth.OAuth2TokenProvider +import com.fsck.k9.mail.oauth.OAuth2TokenProviderFactory +import com.fsck.k9.mail.ssl.LocalKeyStore +import com.fsck.k9.mail.ssl.TrustedSocketFactory +import org.junit.Test +import org.junit.runner.RunWith +import org.koin.android.ext.koin.androidContext +import org.koin.core.annotation.KoinExperimentalAPI +import org.koin.core.module.Module +import org.koin.dsl.koinApplication +import org.koin.dsl.module +import org.koin.test.KoinTest +import org.koin.test.check.checkModules +import org.koin.test.verify.verify +import org.mockito.Mockito +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment + +@RunWith(RobolectricTestRunner::class) +class ServerValidationModuleKtTest : KoinTest { + + private val externalModule: Module = module { + single { + TrustedSocketFactory { _, _, _, _ -> null } + } + single { OAuthConfigurationFactory { emptyMap() } } + single { + OAuth2TokenProviderFactory { _ -> + object : OAuth2TokenProvider { + override fun getToken(timeoutMillis: Long) = TODO() + override fun invalidateToken() = TODO() + } + } + } + single { Mockito.mock() } + } + + @OptIn(KoinExperimentalAPI::class) + @Test + fun `should have a valid di module`() { + featureAccountServerValidationModule.verify( + extraTypes = listOf( + ServerValidationContract.State::class, + AccountDomainContract.AccountStateRepository::class, + AccountServerCertificateDomainContract.ServerCertificateErrorRepository::class, + AccountServerCertificateErrorContract.State::class, + AccountState::class, + Context::class, + Boolean::class, + Class.forName("net.openid.appauth.AppAuthConfiguration").kotlin, + ), + ) + + koinApplication { + modules(externalModule, featureAccountServerValidationModule) + androidContext(RuntimeEnvironment.getApplication()) + checkModules() + } + } +} diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/domain/usecase/FakeAuthStateStorage.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/domain/usecase/FakeAuthStateStorage.kt new file mode 100644 index 0000000000..7158d7a13f --- /dev/null +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/domain/usecase/FakeAuthStateStorage.kt @@ -0,0 +1,13 @@ +package app.k9mail.feature.account.server.validation.domain.usecase + +import com.fsck.k9.mail.oauth.AuthStateStorage + +class FakeAuthStateStorage( + private var authorizationState: String? = null, +) : AuthStateStorage { + override fun getAuthorizationState(): String? = authorizationState + + override fun updateAuthorizationState(authorizationState: String?) { + this.authorizationState = authorizationState + } +} diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServerSettingsTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/domain/usecase/ValidateServerSettingsTest.kt similarity index 96% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServerSettingsTest.kt rename to feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/domain/usecase/ValidateServerSettingsTest.kt index 8fcec7ff2f..a1f7c14580 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServerSettingsTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/domain/usecase/ValidateServerSettingsTest.kt @@ -1,6 +1,5 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.validation.domain.usecase -import app.k9mail.feature.account.setup.ui.validation.InMemoryAuthStateStorage import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType @@ -12,7 +11,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Test class ValidateServerSettingsTest { - private val authStateStorage = InMemoryAuthStateStorage() + private val authStateStorage = FakeAuthStateStorage() @Test fun `should check with imap validator when protocol is imap`() = runTest { diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreenKtTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreenKtTest.kt similarity index 71% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreenKtTest.kt rename to feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreenKtTest.kt index eb3710914d..a4828a420e 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationScreenKtTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreenKtTest.kt @@ -1,27 +1,28 @@ -package app.k9mail.feature.account.setup.ui.validation +package app.k9mail.feature.account.server.validation.ui import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.setContent import app.k9mail.core.ui.compose.theme.ThunderbirdTheme -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.State +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State +import app.k9mail.feature.account.server.validation.ui.fake.FakeServerValidationViewModel import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest import org.junit.Test -class AccountValidationScreenKtTest : ComposeTest() { +class ServerValidationScreenKtTest : ComposeTest() { @Test fun `should delegate navigation effects`() = runTest { val initialState = State() - val viewModel = FakeAccountValidationViewModel(initialState = initialState) + val viewModel = FakeServerValidationViewModel(initialState = initialState) var onNextCounter = 0 var onBackCounter = 0 setContent { ThunderbirdTheme { - AccountValidationScreen( + ServerValidationScreen( onNext = { onNextCounter++ }, onBack = { onBackCounter++ }, viewModel = viewModel, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStateTest.kt similarity index 72% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateTest.kt rename to feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStateTest.kt index ca29ffb3d7..c7d7c4bd9c 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStateTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationStateTest.kt @@ -1,11 +1,11 @@ -package app.k9mail.feature.account.setup.ui.validation +package app.k9mail.feature.account.server.validation.ui -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.State +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test -class AccountValidationStateTest { +class ServerValidationStateTest { @Test fun `should set default values`() { diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt similarity index 94% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt rename to feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt index 91fdfe08ab..f963ccb7fd 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationViewModelTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt @@ -1,16 +1,16 @@ -package app.k9mail.feature.account.setup.ui.validation +package app.k9mail.feature.account.server.validation.ui import app.k9mail.core.ui.compose.testing.MainDispatcherRule import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Error +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository -import app.k9mail.feature.account.setup.ui.FakeAccountOAuthViewModel -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Effect -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Error -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Event -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.State import assertk.assertThat import assertk.assertions.isEqualTo import assertk.assertions.isTrue @@ -23,7 +23,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -class AccountValidationViewModelTest { +class ServerValidationViewModelTest { @get:Rule val mainDispatcherRule = MainDispatcherRule() @@ -191,7 +191,7 @@ class AccountValidationViewModelTest { error = Error.ServerError("server error"), ) var checkSettingsCalled = false - val testSubject = AccountValidationViewModel( + val testSubject = ServerValidationViewModel( validateServerSettings = { delay(50) checkSettingsCalled = true @@ -230,8 +230,8 @@ class AccountValidationViewModelTest { serverSettingsValidationResult: ServerSettingsValidationResult = ServerSettingsValidationResult.Success, accountState: AccountState = AccountState(), initialState: State = State(), - ): AccountValidationViewModel { - return AccountValidationViewModel( + ): ServerValidationViewModel { + return ServerValidationViewModel( validateServerSettings = { delay(50) serverSettingsValidationResult diff --git a/feature/account/setup/build.gradle.kts b/feature/account/setup/build.gradle.kts index a5a9c3dc75..9180fec885 100644 --- a/feature/account/setup/build.gradle.kts +++ b/feature/account/setup/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { api(projects.feature.account.common) implementation(projects.feature.account.oauth) implementation(projects.feature.account.servercertificate) + api(projects.feature.account.server.validation) testImplementation(projects.core.ui.compose.testing) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt index d65b3e03dd..7dfbce6991 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt @@ -4,11 +4,10 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryService import app.k9mail.autodiscovery.service.RealAutoDiscoveryService import app.k9mail.feature.account.common.featureAccountCommonModule import app.k9mail.feature.account.oauth.featureAccountOAuthModule -import app.k9mail.feature.account.servercertificate.featureAccountServerCertificateModule +import app.k9mail.feature.account.server.validation.featureAccountServerValidationModule import app.k9mail.feature.account.setup.domain.DomainContract import app.k9mail.feature.account.setup.domain.usecase.CreateAccount import app.k9mail.feature.account.setup.domain.usecase.GetAutoDiscovery -import app.k9mail.feature.account.setup.domain.usecase.ValidateServerSettings import app.k9mail.feature.account.setup.ui.AccountSetupViewModel import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryValidator @@ -22,18 +21,17 @@ import app.k9mail.feature.account.setup.ui.options.AccountOptionsViewModel import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigValidator import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigViewModel -import app.k9mail.feature.account.setup.ui.validation.AccountValidationViewModel -import com.fsck.k9.mail.store.imap.ImapServerSettingsValidator -import com.fsck.k9.mail.store.pop3.Pop3ServerSettingsValidator -import com.fsck.k9.mail.transport.smtp.SmtpServerSettingsValidator import okhttp3.OkHttpClient import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.core.module.Module -import org.koin.core.qualifier.named import org.koin.dsl.module val featureAccountSetupModule: Module = module { - includes(featureAccountCommonModule, featureAccountOAuthModule, featureAccountServerCertificateModule) + includes( + featureAccountCommonModule, + featureAccountOAuthModule, + featureAccountServerValidationModule, + ) single { OkHttpClient() @@ -52,24 +50,6 @@ val featureAccountSetupModule: Module = module { ) } - factory { - ValidateServerSettings( - authStateStorage = get(), - imapValidator = ImapServerSettingsValidator( - trustedSocketFactory = get(), - oAuth2TokenProviderFactory = get(), - clientIdAppName = "null", - ), - pop3Validator = Pop3ServerSettingsValidator( - trustedSocketFactory = get(), - ), - smtpValidator = SmtpServerSettingsValidator( - trustedSocketFactory = get(), - oAuth2TokenProviderFactory = get(), - ), - ) - } - factory { CreateAccount( accountCreator = get(), @@ -101,32 +81,14 @@ val featureAccountSetupModule: Module = module { accountStateRepository = get(), ) } - viewModel(named(NAME_INCOMING_VALIDATION)) { - AccountValidationViewModel( - validateServerSettings = get(), - accountStateRepository = get(), - authorizationStateRepository = get(), - certificateErrorRepository = get(), - oAuthViewModel = get(), - isIncomingValidation = true, - ) - } + viewModel { AccountOutgoingConfigViewModel( validator = get(), accountStateRepository = get(), ) } - viewModel(named(NAME_OUTGOING_VALIDATION)) { - AccountValidationViewModel( - validateServerSettings = get(), - accountStateRepository = get(), - authorizationStateRepository = get(), - certificateErrorRepository = get(), - oAuthViewModel = get(), - isIncomingValidation = false, - ) - } + viewModel { AccountOptionsViewModel( validator = get(), @@ -134,6 +96,3 @@ val featureAccountSetupModule: Module = module { ) } } - -internal const val NAME_INCOMING_VALIDATION = "incoming_validation" -internal const val NAME_OUTGOING_VALIDATION = "outgoing_validation" diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt index e22b349d33..f7d06c3bce 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt @@ -4,7 +4,6 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryResult import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.feature.account.common.domain.entity.AccountOptions import com.fsck.k9.mail.ServerSettings -import com.fsck.k9.mail.server.ServerSettingsValidationResult import java.security.cert.X509Certificate interface DomainContract { @@ -14,10 +13,6 @@ interface DomainContract { suspend fun execute(emailAddress: String): AutoDiscoveryResult } - fun interface ValidateServerSettings { - suspend fun execute(settings: ServerSettings): ServerSettingsValidationResult - } - fun interface AddServerCertificateException { suspend fun addCertificate(hostname: String, port: Int, certificate: X509Certificate?) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt index 91eb2b013c..b9dd2513d0 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt @@ -3,8 +3,11 @@ package app.k9mail.feature.account.setup.ui import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview import app.k9mail.core.ui.compose.common.mvi.observe -import app.k9mail.feature.account.setup.NAME_INCOMING_VALIDATION -import app.k9mail.feature.account.setup.NAME_OUTGOING_VALIDATION +import app.k9mail.feature.account.server.validation.KOIN_NAME_INCOMING_SERVER_VALIDATION +import app.k9mail.feature.account.server.validation.KOIN_NAME_OUTGOING_SERVER_VALIDATION +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract +import app.k9mail.feature.account.server.validation.ui.ServerValidationScreen +import app.k9mail.feature.account.server.validation.ui.ServerValidationViewModel import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect import app.k9mail.feature.account.setup.ui.AccountSetupContract.Event import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep @@ -21,9 +24,6 @@ import app.k9mail.feature.account.setup.ui.options.AccountOptionsViewModel import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigScreen import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigViewModel -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract -import app.k9mail.feature.account.setup.ui.validation.AccountValidationScreen -import app.k9mail.feature.account.setup.ui.validation.AccountValidationViewModel import org.koin.androidx.compose.koinViewModel import org.koin.core.qualifier.named @@ -35,12 +35,12 @@ fun AccountSetupScreen( viewModel: ViewModel = koinViewModel(), autoDiscoveryViewModel: AccountAutoDiscoveryContract.ViewModel = koinViewModel(), incomingViewModel: AccountIncomingConfigContract.ViewModel = koinViewModel(), - incomingValidationViewModel: AccountValidationContract.ViewModel = koinViewModel( - named(NAME_INCOMING_VALIDATION), + incomingValidationViewModel: ServerValidationContract.ViewModel = koinViewModel( + named(KOIN_NAME_INCOMING_SERVER_VALIDATION), ), outgoingViewModel: AccountOutgoingConfigContract.ViewModel = koinViewModel(), - outgoingValidationViewModel: AccountValidationContract.ViewModel = koinViewModel( - named(NAME_OUTGOING_VALIDATION), + outgoingValidationViewModel: ServerValidationContract.ViewModel = koinViewModel( + named(KOIN_NAME_OUTGOING_SERVER_VALIDATION), ), optionsViewModel: AccountOptionsContract.ViewModel = koinViewModel(), ) { @@ -75,7 +75,7 @@ fun AccountSetupScreen( } SetupStep.INCOMING_VALIDATION -> { - AccountValidationScreen( + ServerValidationScreen( onNext = { dispatch(Event.OnNext) }, onBack = { dispatch(Event.OnBack) }, viewModel = incomingValidationViewModel, @@ -91,7 +91,7 @@ fun AccountSetupScreen( } SetupStep.OUTGOING_VALIDATION -> { - AccountValidationScreen( + ServerValidationScreen( onNext = { dispatch(Event.OnNext) }, onBack = { dispatch(Event.OnBack) }, viewModel = outgoingValidationViewModel, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt index df41531f82..c5f14450d9 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt @@ -9,7 +9,6 @@ import app.k9mail.feature.account.setup.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.setup.domain.input.NumberInputField import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.store.imap.ImapStoreSettings @@ -58,10 +57,3 @@ private fun State.createExtras(): Map { emptyMap() } } - -internal fun State.toValidationState(): AccountValidationContract.State { - return AccountValidationContract.State( - serverSettings = toServerSettings(), - // TODO add authorization state - ) -} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt index e388cdcedf..5694783721 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt @@ -8,7 +8,6 @@ import app.k9mail.feature.account.setup.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.setup.domain.input.NumberInputField import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract import com.fsck.k9.mail.ServerSettings internal fun AccountState.toOutgoingConfigState(): State { @@ -41,10 +40,3 @@ internal fun State.toServerSettings(): ServerSettings { clientCertificateAlias = clientCertificateAlias, ) } - -internal fun State.toValidationState(): AccountValidationContract.State { - return AccountValidationContract.State( - serverSettings = toServerSettings(), - // TODO add authorization state - ) -} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStringMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStringMapper.kt deleted file mode 100644 index 73a7e66ab6..0000000000 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/AccountValidationStringMapper.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.k9mail.feature.account.setup.ui.validation - -import android.content.res.Resources -import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract.Error - -internal fun Error.toResourceString(resources: Resources): String { - return when (this) { - is Error.AuthenticationError -> resources.getString( - R.string.account_setup_settings_validation_error_authentication, - ) - - is Error.CertificateError -> resources.getString( - R.string.account_setup_settings_validation_error_certificate, - ) - - is Error.NetworkError -> resources.getString( - R.string.account_setup_settings_validation_error_network, - ) - - is Error.ServerError -> resources.getString( - R.string.account_setup_settings_validation_error_server, - ) - - is Error.UnknownError -> resources.getString( - R.string.account_setup_settings_validation_error_unknown, - ) - } -} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/InMemoryAuthStateStorage.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/InMemoryAuthStateStorage.kt deleted file mode 100644 index 809d7922c1..0000000000 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/validation/InMemoryAuthStateStorage.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.k9mail.feature.account.setup.ui.validation - -import com.fsck.k9.mail.oauth.AuthStateStorage - -class InMemoryAuthStateStorage : AuthStateStorage { - private var authorizationState: String? = null - - @Synchronized - override fun getAuthorizationState(): String? { - return authorizationState - } - - @Synchronized - override fun updateAuthorizationState(authorizationState: String?) { - this.authorizationState = authorizationState - } -} diff --git a/feature/account/setup/src/main/res/values/strings.xml b/feature/account/setup/src/main/res/values/strings.xml index 4546ad2c94..7197bcb058 100644 --- a/feature/account/setup/src/main/res/values/strings.xml +++ b/feature/account/setup/src/main/res/values/strings.xml @@ -27,19 +27,6 @@ Password is required. Imap prefix can\'t be blank. - Authentication error - Certificate error - Network error - Server error - Unknown error - Checking incoming server settings… - Checking incoming server settings failed! - Incoming server settings are valid! - Checking outgoing server settings… - Checking outgoing server settings failed! - Outgoing server settings are valid! - Please sign in - Finding email details Failed to load email configuration Configuration Found diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index 4d7f20acde..f0ac5169db 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -4,6 +4,7 @@ import android.content.Context import app.k9mail.core.common.oauth.OAuthConfigurationFactory import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult @@ -12,7 +13,6 @@ import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryCon import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract -import app.k9mail.feature.account.setup.ui.validation.AccountValidationContract import com.fsck.k9.mail.oauth.AuthStateStorage import com.fsck.k9.mail.oauth.OAuth2TokenProvider import com.fsck.k9.mail.oauth.OAuth2TokenProviderFactory @@ -64,7 +64,7 @@ class AccountSetupModuleKtTest : KoinTest { AccountSetupContract.State::class, AccountAutoDiscoveryContract.State::class, AccountOAuthContract.State::class, - AccountValidationContract.State::class, + ServerValidationContract.State::class, AccountIncomingConfigContract.State::class, AccountOutgoingConfigContract.State::class, AccountOptionsContract.State::class, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt index 2bcbef2fed..2226f350db 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt @@ -4,6 +4,7 @@ import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.onNodeWithTag import app.k9mail.core.ui.compose.testing.setContent import app.k9mail.core.ui.compose.theme.ThunderbirdTheme +import app.k9mail.feature.account.server.validation.ui.fake.FakeServerValidationViewModel import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep import app.k9mail.feature.account.setup.ui.AccountSetupContract.State @@ -11,7 +12,6 @@ import app.k9mail.feature.account.setup.ui.autodiscovery.FakeAccountAutoDiscover import app.k9mail.feature.account.setup.ui.incoming.FakeAccountIncomingConfigViewModel import app.k9mail.feature.account.setup.ui.options.FakeAccountOptionsViewModel import app.k9mail.feature.account.setup.ui.outgoing.FakeAccountOutgoingConfigViewModel -import app.k9mail.feature.account.setup.ui.validation.FakeAccountValidationViewModel import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest @@ -31,9 +31,9 @@ class AccountSetupScreenKtTest : ComposeTest() { viewModel = viewModel, autoDiscoveryViewModel = FakeAccountAutoDiscoveryViewModel(), incomingViewModel = FakeAccountIncomingConfigViewModel(), - incomingValidationViewModel = FakeAccountValidationViewModel(), + incomingValidationViewModel = FakeServerValidationViewModel(), outgoingViewModel = FakeAccountOutgoingConfigViewModel(), - outgoingValidationViewModel = FakeAccountValidationViewModel(), + outgoingValidationViewModel = FakeServerValidationViewModel(), optionsViewModel = FakeAccountOptionsViewModel(), ) } @@ -60,9 +60,9 @@ class AccountSetupScreenKtTest : ComposeTest() { viewModel = viewModel, autoDiscoveryViewModel = FakeAccountAutoDiscoveryViewModel(), incomingViewModel = FakeAccountIncomingConfigViewModel(), - incomingValidationViewModel = FakeAccountValidationViewModel(), + incomingValidationViewModel = FakeServerValidationViewModel(), outgoingViewModel = FakeAccountOutgoingConfigViewModel(), - outgoingValidationViewModel = FakeAccountValidationViewModel(), + outgoingValidationViewModel = FakeServerValidationViewModel(), optionsViewModel = FakeAccountOptionsViewModel(), ) } diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt index 3f13d83dcb..91b00324a2 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt @@ -10,10 +10,10 @@ import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel import app.k9mail.feature.account.setup.domain.entity.AutoDiscoverySettingsFixture import app.k9mail.feature.account.setup.domain.input.BooleanInputField import app.k9mail.feature.account.setup.domain.input.StringInputField -import app.k9mail.feature.account.setup.ui.FakeAccountOAuthViewModel import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.ConfigStep import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.Effect import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.Error diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/FakeAccountAutoDiscoveryViewModel.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/FakeAccountAutoDiscoveryViewModel.kt index a33c8373bd..c4d372ae21 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/FakeAccountAutoDiscoveryViewModel.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/FakeAccountAutoDiscoveryViewModel.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.setup.ui.autodiscovery import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.oauth.ui.AccountOAuthContract -import app.k9mail.feature.account.setup.ui.FakeAccountOAuthViewModel +import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.Effect import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.Event import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.State diff --git a/settings.gradle.kts b/settings.gradle.kts index 6e63d46624..c34e383d8e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -48,6 +48,7 @@ include( ":feature:account:oauth", ":feature:account:servercertificate", ":feature:account:setup", + ":feature:account:server:validation", ) include( -- GitLab From dcad7a95b615c6f85a6f8a153d1de92a654e37aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 5 Sep 2023 17:10:44 +0200 Subject: [PATCH 14/94] Move server certificate to server module --- .../com/fsck/k9/DependencyInjectionTest.kt | 8 +++-- .../certificate}/build.gradle.kts | 4 +-- .../certificate/ServerCertificateModule.kt | 29 +++++++++++++++++++ ...nMemoryServerCertificateErrorRepository.kt | 8 ++--- .../ServerCertificateDomainContract.kt} | 6 ++-- .../domain/entity/ServerCertificateError.kt | 2 +- .../usecase/AddServerCertificateException.kt | 4 +-- .../ui/ServerCertificateErrorContract.kt} | 4 +-- .../ui/ServerCertificateErrorScreen.kt} | 22 +++++++------- .../ui/ServerCertificateErrorViewModel.kt} | 20 ++++++------- .../ServerCertificateModuleKtTest.kt} | 8 ++--- .../server/validation/build.gradle.kts | 2 +- .../validation/ServerValidationModule.kt | 2 +- .../ui/ServerValidationMainScreen.kt | 2 +- .../validation/ui/ServerValidationScreen.kt | 4 +-- .../ui/ServerValidationViewModel.kt | 6 ++-- .../ServerValidationModuleKtTest.kt | 8 ++--- .../ui/ServerValidationViewModelTest.kt | 2 +- .../AccountServerCertificateModule.kt | 29 ------------------- feature/account/setup/build.gradle.kts | 2 +- .../account/setup/AccountSetupModuleKtTest.kt | 4 +-- settings.gradle.kts | 2 +- 22 files changed, 91 insertions(+), 87 deletions(-) rename feature/account/{servercertificate => server/certificate}/build.gradle.kts (74%) create mode 100644 feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ServerCertificateModule.kt rename feature/account/{servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate => server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate}/data/InMemoryServerCertificateErrorRepository.kt (59%) rename feature/account/{servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt => server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/domain/ServerCertificateDomainContract.kt} (70%) rename feature/account/{servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate => server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate}/domain/entity/ServerCertificateError.kt (72%) rename feature/account/{servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate => server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate}/domain/usecase/AddServerCertificateException.kt (78%) rename feature/account/{servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt => server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorContract.kt} (81%) rename feature/account/{servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt => server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorScreen.kt} (89%) rename feature/account/{servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt => server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorViewModel.kt} (79%) rename feature/account/{servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt => server/certificate/src/test/kotlin/app/k9mail/feature/account/server/certificate/ServerCertificateModuleKtTest.kt} (74%) delete mode 100644 feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt diff --git a/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt b/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt index f3cbf1e39c..3593d9fbae 100644 --- a/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt +++ b/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt @@ -61,8 +61,12 @@ class DependencyInjectionTest : AutoCloseKoinTest() { withParameters(clazz = Class.forName("com.fsck.k9.view.K9WebViewClient").kotlin) { parametersOf(null, null) } - withParameter(named(KOIN_NAME_INCOMING_SERVER_VALIDATION)) { authStateStorage } - withParameter(named(KOIN_NAME_OUTGOING_SERVER_VALIDATION)) { authStateStorage } + withParameter( + named(KOIN_NAME_INCOMING_SERVER_VALIDATION), + ) { authStateStorage } + withParameter( + named(KOIN_NAME_OUTGOING_SERVER_VALIDATION), + ) { authStateStorage } withParameter { authStateStorage } withParameter { mock() } } diff --git a/feature/account/servercertificate/build.gradle.kts b/feature/account/server/certificate/build.gradle.kts similarity index 74% rename from feature/account/servercertificate/build.gradle.kts rename to feature/account/server/certificate/build.gradle.kts index ac04d5f407..a392d29943 100644 --- a/feature/account/servercertificate/build.gradle.kts +++ b/feature/account/server/certificate/build.gradle.kts @@ -3,8 +3,8 @@ plugins { } android { - namespace = "app.k9mail.feature.account.servercertificate" - resourcePrefix = "account_servercertificate_" + namespace = "app.k9mail.feature.account.server.certificate" + resourcePrefix = "account_server_certificate_" } dependencies { diff --git a/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ServerCertificateModule.kt b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ServerCertificateModule.kt new file mode 100644 index 0000000000..8f006c1278 --- /dev/null +++ b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ServerCertificateModule.kt @@ -0,0 +1,29 @@ +package app.k9mail.feature.account.server.certificate + +import app.k9mail.feature.account.server.certificate.data.InMemoryServerCertificateErrorRepository +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract +import app.k9mail.feature.account.server.certificate.domain.usecase.AddServerCertificateException +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorViewModel +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.core.module.Module +import org.koin.dsl.module + +val featureAccountServerCertificateModule: Module = module { + + single { + InMemoryServerCertificateErrorRepository() + } + + factory { + AddServerCertificateException( + localKeyStore = get(), + ) + } + + viewModel { + ServerCertificateErrorViewModel( + certificateErrorRepository = get(), + addServerCertificateException = get(), + ) + } +} diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/data/InMemoryServerCertificateErrorRepository.kt similarity index 59% rename from feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt rename to feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/data/InMemoryServerCertificateErrorRepository.kt index 61a2786ee8..f07bd32283 100644 --- a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/data/InMemoryServerCertificateErrorRepository.kt +++ b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/data/InMemoryServerCertificateErrorRepository.kt @@ -1,11 +1,11 @@ -package app.k9mail.feature.account.servercertificate.data +package app.k9mail.feature.account.server.certificate.data -import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract -import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract +import app.k9mail.feature.account.server.certificate.domain.entity.ServerCertificateError class InMemoryServerCertificateErrorRepository( private var serverCertificateError: ServerCertificateError? = null, -) : AccountServerCertificateDomainContract.ServerCertificateErrorRepository { +) : ServerCertificateDomainContract.ServerCertificateErrorRepository { override fun getCertificateError(): ServerCertificateError? { return serverCertificateError diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/domain/ServerCertificateDomainContract.kt similarity index 70% rename from feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt rename to feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/domain/ServerCertificateDomainContract.kt index dd5d8e8ee5..66700cc34b 100644 --- a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/AccountServerCertificateDomainContract.kt +++ b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/domain/ServerCertificateDomainContract.kt @@ -1,9 +1,9 @@ -package app.k9mail.feature.account.servercertificate.domain +package app.k9mail.feature.account.server.certificate.domain -import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError +import app.k9mail.feature.account.server.certificate.domain.entity.ServerCertificateError import java.security.cert.X509Certificate -interface AccountServerCertificateDomainContract { +interface ServerCertificateDomainContract { interface ServerCertificateErrorRepository { fun getCertificateError(): ServerCertificateError? diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/domain/entity/ServerCertificateError.kt similarity index 72% rename from feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt rename to feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/domain/entity/ServerCertificateError.kt index 796b6d41a7..5a558ad590 100644 --- a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/entity/ServerCertificateError.kt +++ b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/domain/entity/ServerCertificateError.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.servercertificate.domain.entity +package app.k9mail.feature.account.server.certificate.domain.entity import java.security.cert.X509Certificate diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/usecase/AddServerCertificateException.kt b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/domain/usecase/AddServerCertificateException.kt similarity index 78% rename from feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/usecase/AddServerCertificateException.kt rename to feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/domain/usecase/AddServerCertificateException.kt index baf3c3d4fe..de65461cc5 100644 --- a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/domain/usecase/AddServerCertificateException.kt +++ b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/domain/usecase/AddServerCertificateException.kt @@ -1,6 +1,6 @@ -package app.k9mail.feature.account.servercertificate.domain.usecase +package app.k9mail.feature.account.server.certificate.domain.usecase -import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract.UseCase +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract.UseCase import com.fsck.k9.mail.ssl.LocalKeyStore import java.security.cert.X509Certificate import kotlinx.coroutines.CoroutineDispatcher diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorContract.kt similarity index 81% rename from feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt rename to feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorContract.kt index e5f21ab86d..60278650b5 100644 --- a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorContract.kt +++ b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorContract.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.servercertificate.ui +package app.k9mail.feature.account.server.certificate.ui import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel -interface AccountServerCertificateErrorContract { +interface ServerCertificateErrorContract { interface ViewModel : UnidirectionalViewModel diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorScreen.kt similarity index 89% rename from feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt rename to feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorScreen.kt index 7c0a4343a2..bcf6bc6336 100644 --- a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorScreen.kt +++ b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorScreen.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.servercertificate.ui +package app.k9mail.feature.account.server.certificate.ui import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Column @@ -21,11 +21,11 @@ import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer import app.k9mail.core.ui.compose.designsystem.template.Scaffold import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.MainTheme -import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository -import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError -import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Effect -import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Event -import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.ViewModel +import app.k9mail.feature.account.server.certificate.data.InMemoryServerCertificateErrorRepository +import app.k9mail.feature.account.server.certificate.domain.entity.ServerCertificateError +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract.Effect +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract.Event +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract.ViewModel import java.security.cert.CertificateFactory import java.security.cert.X509Certificate import org.koin.androidx.compose.koinViewModel @@ -33,11 +33,11 @@ import org.koin.androidx.compose.koinViewModel // Note: This is a placeholder with mostly hardcoded text. // TODO: Replace with final design. @Composable -fun CertificateErrorScreen( +fun ServerCertificateErrorScreen( onCertificateAccepted: () -> Unit, onBack: () -> Unit, modifier: Modifier = Modifier, - viewModel: ViewModel = koinViewModel(), + viewModel: ViewModel = koinViewModel(), ) { val (state, dispatch) = viewModel.observe { effect -> when (effect) { @@ -102,7 +102,7 @@ fun CertificateErrorScreen( @Composable @DevicePreviews -internal fun CertificateErrorScreenK9Preview() { +internal fun ServerCertificateErrorScreenK9Preview() { val inputStream = """ -----BEGIN CERTIFICATE----- MIIE8jCCA9qgAwIBAgISA3bsPKY1eoe/RiBO2t8fUvh1MA0GCSqGSIb3DQEBCwUA @@ -145,10 +145,10 @@ internal fun CertificateErrorScreenK9Preview() { ) K9Theme { - CertificateErrorScreen( + ServerCertificateErrorScreen( onCertificateAccepted = {}, onBack = {}, - viewModel = AccountServerCertificateErrorViewModel( + viewModel = ServerCertificateErrorViewModel( addServerCertificateException = { _, _, _ -> }, certificateErrorRepository = InMemoryServerCertificateErrorRepository(serverCertificateError), ), diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorViewModel.kt similarity index 79% rename from feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt rename to feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorViewModel.kt index 58641a40b8..15184b6033 100644 --- a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/ui/AccountServerCertificateErrorViewModel.kt +++ b/feature/account/server/certificate/src/main/kotlin/app/k9mail/feature/account/server/certificate/ui/ServerCertificateErrorViewModel.kt @@ -1,13 +1,13 @@ -package app.k9mail.feature.account.servercertificate.ui +package app.k9mail.feature.account.server.certificate.ui import androidx.lifecycle.viewModelScope import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract -import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract.UseCase -import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError -import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Effect -import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.Event -import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract.State +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract.UseCase +import app.k9mail.feature.account.server.certificate.domain.entity.ServerCertificateError +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract.Effect +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract.Event +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract.State import com.fsck.k9.logging.Timber import com.fsck.k9.mail.filter.Hex import java.security.MessageDigest @@ -15,11 +15,11 @@ import java.security.NoSuchAlgorithmException import java.security.cert.CertificateEncodingException import kotlinx.coroutines.launch -class AccountServerCertificateErrorViewModel( - private val certificateErrorRepository: AccountServerCertificateDomainContract.ServerCertificateErrorRepository, +class ServerCertificateErrorViewModel( + private val certificateErrorRepository: ServerCertificateDomainContract.ServerCertificateErrorRepository, private val addServerCertificateException: UseCase.AddServerCertificateException, initialState: State = State(), -) : BaseViewModel(initialState), AccountServerCertificateErrorContract.ViewModel { +) : BaseViewModel(initialState), ServerCertificateErrorContract.ViewModel { private val serverCertificateError: ServerCertificateError? = certificateErrorRepository.getCertificateError() init { diff --git a/feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt b/feature/account/server/certificate/src/test/kotlin/app/k9mail/feature/account/server/certificate/ServerCertificateModuleKtTest.kt similarity index 74% rename from feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt rename to feature/account/server/certificate/src/test/kotlin/app/k9mail/feature/account/server/certificate/ServerCertificateModuleKtTest.kt index 2009862fb9..0247bd8b3e 100644 --- a/feature/account/servercertificate/src/test/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModuleKtTest.kt +++ b/feature/account/server/certificate/src/test/kotlin/app/k9mail/feature/account/server/certificate/ServerCertificateModuleKtTest.kt @@ -1,6 +1,6 @@ -package app.k9mail.feature.account.servercertificate +package app.k9mail.feature.account.server.certificate -import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract import com.fsck.k9.mail.ssl.LocalKeyStore import org.junit.Test import org.koin.core.annotation.KoinExperimentalAPI @@ -12,7 +12,7 @@ import org.koin.test.check.checkModules import org.koin.test.verify.verify import org.mockito.Mockito -class AccountServerCertificateModuleKtTest : KoinTest { +class ServerCertificateModuleKtTest : KoinTest { private val externalModule: Module = module { single { Mockito.mock() } @@ -23,7 +23,7 @@ class AccountServerCertificateModuleKtTest : KoinTest { fun `should have a valid di module`() { featureAccountServerCertificateModule.verify( extraTypes = listOf( - AccountServerCertificateErrorContract.State::class, + ServerCertificateErrorContract.State::class, ), ) diff --git a/feature/account/server/validation/build.gradle.kts b/feature/account/server/validation/build.gradle.kts index aa23f22b6b..75c9d1be0e 100644 --- a/feature/account/server/validation/build.gradle.kts +++ b/feature/account/server/validation/build.gradle.kts @@ -27,7 +27,7 @@ dependencies { implementation(projects.feature.account.common) implementation(projects.feature.account.oauth) - implementation(projects.feature.account.servercertificate) + implementation(projects.feature.account.server.certificate) testImplementation(projects.core.ui.compose.testing) } diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt index 3fe94c8b25..6c9bc29e70 100644 --- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt @@ -3,10 +3,10 @@ package app.k9mail.feature.account.server.validation import app.k9mail.core.common.coreCommonModule import app.k9mail.feature.account.common.featureAccountCommonModule import app.k9mail.feature.account.oauth.featureAccountOAuthModule +import app.k9mail.feature.account.server.certificate.featureAccountServerCertificateModule import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract import app.k9mail.feature.account.server.validation.domain.usecase.ValidateServerSettings import app.k9mail.feature.account.server.validation.ui.ServerValidationViewModel -import app.k9mail.feature.account.servercertificate.featureAccountServerCertificateModule import com.fsck.k9.mail.store.imap.ImapServerSettingsValidator import com.fsck.k9.mail.store.pop3.Pop3ServerSettingsValidator import com.fsck.k9.mail.transport.smtp.SmtpServerSettingsValidator diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt index 0e34bad7e0..0d1db380f8 100644 --- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt @@ -12,9 +12,9 @@ import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.WizardNavigationBarState import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.oauth.ui.preview.PreviewAccountOAuthViewModel +import app.k9mail.feature.account.server.certificate.data.InMemoryServerCertificateErrorRepository import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.ViewModel -import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository import com.fsck.k9.mail.server.ServerSettingsValidationResult @Composable diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreen.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreen.kt index 5e79d0854e..32f16da0d1 100644 --- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreen.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationScreen.kt @@ -5,10 +5,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import app.k9mail.core.ui.compose.common.mvi.observe +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorScreen import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.ViewModel -import app.k9mail.feature.account.servercertificate.ui.CertificateErrorScreen @Composable fun ServerValidationScreen( @@ -33,7 +33,7 @@ fun ServerValidationScreen( } if (state.value.error is ServerValidationContract.Error.CertificateError) { - CertificateErrorScreen( + ServerCertificateErrorScreen( onCertificateAccepted = { dispatch(Event.OnCertificateAccepted) }, onBack = { dispatch(Event.OnBackClicked) }, modifier = modifier, diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt index 15653a7c4e..bdd457c3ef 100644 --- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt @@ -7,13 +7,13 @@ import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.domain.entity.isOAuth import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract +import app.k9mail.feature.account.server.certificate.domain.entity.ServerCertificateError import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Error import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State -import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract -import app.k9mail.feature.account.servercertificate.domain.entity.ServerCertificateError import com.fsck.k9.mail.server.ServerSettingsValidationResult import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.delay @@ -26,7 +26,7 @@ class ServerValidationViewModel( private val accountStateRepository: AccountDomainContract.AccountStateRepository, private val validateServerSettings: ServerValidationDomainContract.UseCase.ValidateServerSettings, private val authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, - private val certificateErrorRepository: AccountServerCertificateDomainContract.ServerCertificateErrorRepository, + private val certificateErrorRepository: ServerCertificateDomainContract.ServerCertificateErrorRepository, override val oAuthViewModel: AccountOAuthContract.ViewModel, override val isIncomingValidation: Boolean = true, initialState: State? = null, diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt index a7444692b5..e6d2f7bdae 100644 --- a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt @@ -4,9 +4,9 @@ import android.content.Context import app.k9mail.core.common.oauth.OAuthConfigurationFactory import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract import app.k9mail.feature.account.server.validation.ui.ServerValidationContract -import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract -import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract import com.fsck.k9.mail.oauth.OAuth2TokenProvider import com.fsck.k9.mail.oauth.OAuth2TokenProviderFactory import com.fsck.k9.mail.ssl.LocalKeyStore @@ -51,8 +51,8 @@ class ServerValidationModuleKtTest : KoinTest { extraTypes = listOf( ServerValidationContract.State::class, AccountDomainContract.AccountStateRepository::class, - AccountServerCertificateDomainContract.ServerCertificateErrorRepository::class, - AccountServerCertificateErrorContract.State::class, + ServerCertificateDomainContract.ServerCertificateErrorRepository::class, + ServerCertificateErrorContract.State::class, AccountState::class, Context::class, Boolean::class, diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt index f963ccb7fd..a482fdf65d 100644 --- a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt @@ -6,11 +6,11 @@ import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel +import app.k9mail.feature.account.server.certificate.data.InMemoryServerCertificateErrorRepository import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Error import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State -import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository import assertk.assertThat import assertk.assertions.isEqualTo import assertk.assertions.isTrue diff --git a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt b/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt deleted file mode 100644 index 94de6d5e3a..0000000000 --- a/feature/account/servercertificate/src/main/kotlin/app/k9mail/feature/account/servercertificate/AccountServerCertificateModule.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.k9mail.feature.account.servercertificate - -import app.k9mail.feature.account.servercertificate.data.InMemoryServerCertificateErrorRepository -import app.k9mail.feature.account.servercertificate.domain.AccountServerCertificateDomainContract -import app.k9mail.feature.account.servercertificate.domain.usecase.AddServerCertificateException -import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorViewModel -import org.koin.androidx.viewmodel.dsl.viewModel -import org.koin.core.module.Module -import org.koin.dsl.module - -val featureAccountServerCertificateModule: Module = module { - - single { - InMemoryServerCertificateErrorRepository() - } - - factory { - AddServerCertificateException( - localKeyStore = get(), - ) - } - - viewModel { - AccountServerCertificateErrorViewModel( - certificateErrorRepository = get(), - addServerCertificateException = get(), - ) - } -} diff --git a/feature/account/setup/build.gradle.kts b/feature/account/setup/build.gradle.kts index 9180fec885..697507561c 100644 --- a/feature/account/setup/build.gradle.kts +++ b/feature/account/setup/build.gradle.kts @@ -29,7 +29,7 @@ dependencies { api(projects.feature.account.common) implementation(projects.feature.account.oauth) - implementation(projects.feature.account.servercertificate) + implementation(projects.feature.account.server.certificate) api(projects.feature.account.server.validation) testImplementation(projects.core.ui.compose.testing) diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index f0ac5169db..da60b42513 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -4,8 +4,8 @@ import android.content.Context import app.k9mail.core.common.oauth.OAuthConfigurationFactory import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract import app.k9mail.feature.account.server.validation.ui.ServerValidationContract -import app.k9mail.feature.account.servercertificate.ui.AccountServerCertificateErrorContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult import app.k9mail.feature.account.setup.ui.AccountSetupContract @@ -69,7 +69,7 @@ class AccountSetupModuleKtTest : KoinTest { AccountOutgoingConfigContract.State::class, AccountOptionsContract.State::class, AccountState::class, - AccountServerCertificateErrorContract.State::class, + ServerCertificateErrorContract.State::class, AuthStateStorage::class, Context::class, Boolean::class, diff --git a/settings.gradle.kts b/settings.gradle.kts index c34e383d8e..4c7e49384a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -46,8 +46,8 @@ include( include( ":feature:account:common", ":feature:account:oauth", - ":feature:account:servercertificate", ":feature:account:setup", + ":feature:account:server:certificate", ":feature:account:server:validation", ) -- GitLab From 26e4ee5d5297bf9af5b46af7d8a8410eb6136dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 5 Sep 2023 17:40:58 +0200 Subject: [PATCH 15/94] Move InputFields to account common module --- .../feature/account/common}/domain/input/BooleanInputField.kt | 2 +- .../k9mail/feature/account/common}/domain/input/InputField.kt | 2 +- .../feature/account/common}/domain/input/NumberInputField.kt | 2 +- .../feature/account/common}/domain/input/StringInputField.kt | 2 +- .../feature/account/common}/domain/input/InputFieldTest.kt | 2 +- .../setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt | 4 ++-- .../setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt | 4 ++-- .../setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt | 2 +- .../setup/ui/autodiscovery/item/ConfigurationApprovalItem.kt | 2 +- .../setup/ui/autodiscovery/view/ConfigurationApprovalView.kt | 2 +- .../setup/ui/incoming/AccountIncomingConfigContract.kt | 4 ++-- .../setup/ui/incoming/AccountIncomingConfigStateMapper.kt | 4 ++-- .../account/setup/ui/options/AccountOptionsContract.kt | 2 +- .../account/setup/ui/options/AccountOptionsStateMapper.kt | 2 +- .../setup/ui/outgoing/AccountOutgoingConfigContract.kt | 4 ++-- .../setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt | 4 ++-- .../ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt | 4 ++-- .../setup/ui/autodiscovery/AccountAutoDiscoveryStateTest.kt | 4 ++-- .../ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt | 4 ++-- .../ui/incoming/AccountIncomingConfigStateMapperKtTest.kt | 4 ++-- .../setup/ui/incoming/AccountIncomingConfigStateTest.kt | 4 ++-- .../setup/ui/incoming/AccountIncomingConfigViewModelTest.kt | 4 ++-- .../setup/ui/options/AccountOptionsStateMapperKtTest.kt | 2 +- .../account/setup/ui/options/AccountOptionsStateTest.kt | 2 +- .../account/setup/ui/options/AccountOptionsViewModelTest.kt | 2 +- .../ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt | 4 ++-- .../setup/ui/outgoing/AccountOutgoingConfigStateTest.kt | 4 ++-- .../setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt | 4 ++-- 28 files changed, 43 insertions(+), 43 deletions(-) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/input/BooleanInputField.kt (97%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/input/InputField.kt (96%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/input/NumberInputField.kt (97%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/input/StringInputField.kt (97%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => common/src/test/kotlin/app/k9mail/feature/account/common}/domain/input/InputFieldTest.kt (99%) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/BooleanInputField.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/BooleanInputField.kt similarity index 97% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/BooleanInputField.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/BooleanInputField.kt index 561e562572..273179c753 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/BooleanInputField.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/BooleanInputField.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.input +package app.k9mail.feature.account.common.domain.input import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/InputField.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/InputField.kt similarity index 96% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/InputField.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/InputField.kt index 9aa75019fd..d5d2925a61 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/InputField.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/InputField.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.input +package app.k9mail.feature.account.common.domain.input import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/NumberInputField.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/NumberInputField.kt similarity index 97% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/NumberInputField.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/NumberInputField.kt index 34b8a82513..966e18645f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/NumberInputField.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/NumberInputField.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.input +package app.k9mail.feature.account.common.domain.input import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/StringInputField.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/StringInputField.kt similarity index 97% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/StringInputField.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/StringInputField.kt index a793eb5320..96c1cc68cb 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/input/StringInputField.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/input/StringInputField.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.input +package app.k9mail.feature.account.common.domain.input import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/input/InputFieldTest.kt b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/input/InputFieldTest.kt similarity index 99% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/input/InputFieldTest.kt rename to feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/input/InputFieldTest.kt index af3ae423ea..056edec7f8 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/input/InputFieldTest.kt +++ b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/input/InputFieldTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.input +package app.k9mail.feature.account.common.domain.input import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt index f8ae81ddc8..e7a0ca443b 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt @@ -4,10 +4,10 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryResult import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel import app.k9mail.feature.account.common.domain.entity.AuthorizationState +import app.k9mail.feature.account.common.domain.input.BooleanInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.ui.AccountOAuthContract -import app.k9mail.feature.account.setup.domain.input.BooleanInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField interface AccountAutoDiscoveryContract { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt index ef50aba7a3..5cea5b8cd0 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt @@ -3,11 +3,11 @@ package app.k9mail.feature.account.setup.ui.autodiscovery import app.k9mail.autodiscovery.api.ImapServerSettings import app.k9mail.autodiscovery.api.SmtpServerSettings import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toIncomingProtocolType -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.toServerSettings import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt index 43d76616d8..ec2f920bfa 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt @@ -6,11 +6,11 @@ import app.k9mail.autodiscovery.api.ImapServerSettings import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.oauth.domain.entity.OAuthResult import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.setup.domain.DomainContract.UseCase import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.ConfigStep import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.Effect import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.Error diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ConfigurationApprovalItem.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ConfigurationApprovalItem.kt index dc7bac3096..ed1bdb6ad7 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ConfigurationApprovalItem.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ConfigurationApprovalItem.kt @@ -3,8 +3,8 @@ package app.k9mail.feature.account.setup.ui.autodiscovery.item import androidx.compose.foundation.lazy.LazyItemScope import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import app.k9mail.feature.account.common.domain.input.BooleanInputField import app.k9mail.feature.account.common.ui.item.ListItem -import app.k9mail.feature.account.setup.domain.input.BooleanInputField import app.k9mail.feature.account.setup.ui.autodiscovery.view.ConfigurationApprovalView @Composable diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt index 2bd6c81b27..26e0ad170a 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt @@ -9,8 +9,8 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import app.k9mail.core.ui.compose.designsystem.molecule.input.CheckboxInput import app.k9mail.core.ui.compose.theme.MainTheme +import app.k9mail.feature.account.common.domain.input.BooleanInputField import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.domain.input.BooleanInputField import app.k9mail.feature.account.setup.ui.autodiscovery.toResourceString @Composable diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt index 304bcd5ad7..1a73dc68b9 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt @@ -2,12 +2,12 @@ package app.k9mail.feature.account.setup.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType import app.k9mail.feature.account.setup.domain.entity.toDefaultPort -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField interface AccountIncomingConfigContract { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt index c5f14450d9..3d3285e15f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt @@ -1,13 +1,13 @@ package app.k9mail.feature.account.setup.ui.incoming import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType import app.k9mail.feature.account.setup.domain.entity.toAuthType import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toMailConnectionSecurity -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.store.imap.ImapStoreSettings diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsContract.kt index 6717c65795..0b536d7110 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsContract.kt @@ -2,9 +2,9 @@ package app.k9mail.feature.account.setup.ui.options import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.EmailCheckFrequency import app.k9mail.feature.account.setup.domain.entity.EmailDisplayCount -import app.k9mail.feature.account.setup.domain.input.StringInputField interface AccountOptionsContract { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapper.kt index f9aca0adaf..3d4c503022 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapper.kt @@ -2,9 +2,9 @@ package app.k9mail.feature.account.setup.ui.options import app.k9mail.feature.account.common.domain.entity.AccountOptions import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.EmailCheckFrequency import app.k9mail.feature.account.setup.domain.entity.EmailDisplayCount -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.State internal fun AccountState.toAccountOptionsState(): State { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt index 7373a80c2c..b1c83e27de 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt @@ -2,11 +2,11 @@ package app.k9mail.feature.account.setup.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toSmtpDefaultPort -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField interface AccountOutgoingConfigContract { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt index 5694783721..15f477c345 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt @@ -1,12 +1,12 @@ package app.k9mail.feature.account.setup.ui.outgoing import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.toAuthType import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toMailConnectionSecurity -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State import com.fsck.k9.mail.ServerSettings diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt index 05f99c2e16..1fa7237794 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt @@ -6,13 +6,13 @@ import app.k9mail.autodiscovery.api.SmtpServerSettings import app.k9mail.core.common.net.toHostname import app.k9mail.core.common.net.toPort import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateTest.kt index fee85038cd..8fcfff3eef 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateTest.kt @@ -1,7 +1,7 @@ package app.k9mail.feature.account.setup.ui.autodiscovery -import app.k9mail.feature.account.setup.domain.input.BooleanInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField +import app.k9mail.feature.account.common.domain.input.BooleanInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.ConfigStep import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.State import assertk.assertThat diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt index 91b00324a2..0d38937df4 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt @@ -10,10 +10,10 @@ import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.input.BooleanInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel import app.k9mail.feature.account.setup.domain.entity.AutoDiscoverySettingsFixture -import app.k9mail.feature.account.setup.domain.input.BooleanInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.ConfigStep import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.Effect import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract.Error diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt index e37fa01a7c..93a53158a7 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt @@ -1,11 +1,11 @@ package app.k9mail.feature.account.setup.ui.incoming import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt index b1bdf26301..1b0120efcb 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt @@ -1,11 +1,11 @@ package app.k9mail.feature.account.setup.ui.incoming +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType import app.k9mail.feature.account.setup.domain.entity.toImapDefaultPort -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt index 77b6f0a7ed..b0568ad9d1 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt @@ -11,13 +11,13 @@ import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType import app.k9mail.feature.account.setup.domain.entity.toImapDefaultPort import app.k9mail.feature.account.setup.domain.entity.toPop3DefaultPort -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapperKtTest.kt index 84b9991741..cfaa6c1e05 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateMapperKtTest.kt @@ -1,9 +1,9 @@ package app.k9mail.feature.account.setup.ui.options import app.k9mail.feature.account.common.domain.entity.AccountOptions +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.EmailCheckFrequency import app.k9mail.feature.account.setup.domain.entity.EmailDisplayCount -import app.k9mail.feature.account.setup.domain.input.StringInputField import assertk.assertThat import assertk.assertions.isEqualTo import assertk.assertions.isNull diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateTest.kt index eeb7ec44e4..40526d7013 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsStateTest.kt @@ -1,8 +1,8 @@ package app.k9mail.feature.account.setup.ui.options +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.EmailCheckFrequency import app.k9mail.feature.account.setup.domain.entity.EmailDisplayCount -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.State import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModelTest.kt index 3b9ff7d657..f610c02494 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModelTest.kt @@ -6,9 +6,9 @@ import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.testing.MainDispatcherRule import app.k9mail.core.ui.compose.testing.mvi.eventStateTest import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.EmailCheckFrequency import app.k9mail.feature.account.setup.domain.entity.EmailDisplayCount -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.Effect import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.Event import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.State diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt index 53eec173b6..dfb1461c12 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt @@ -1,10 +1,10 @@ package app.k9mail.feature.account.setup.ui.outgoing import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt index 840fbe5601..f9328447af 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt @@ -1,10 +1,10 @@ package app.k9mail.feature.account.setup.ui.outgoing +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toSmtpDefaultPort -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt index 881ae5b65e..1945c902bc 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt @@ -11,11 +11,11 @@ import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toSmtpDefaultPort -import app.k9mail.feature.account.setup.domain.input.NumberInputField -import app.k9mail.feature.account.setup.domain.input.StringInputField import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State -- GitLab From 875dd8f464465a7e069b9e62fb33f38331e8744b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 11:58:15 +0200 Subject: [PATCH 16/94] Move AccountSetupTopAppBar to common and rename to AccountTopAppBar --- .../account/common/ui/AccountTopAppBar.kt} | 19 +++++++++++-------- .../incoming/AccountIncomingConfigScreen.kt | 4 ++-- .../setup/ui/options/AccountOptionsScreen.kt | 4 ++-- .../outgoing/AccountOutgoingConfigScreen.kt | 4 ++-- 4 files changed, 17 insertions(+), 14 deletions(-) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupTopAppBar.kt => common/src/main/kotlin/app/k9mail/feature/account/common/ui/AccountTopAppBar.kt} (65%) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupTopAppBar.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/AccountTopAppBar.kt similarity index 65% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupTopAppBar.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/AccountTopAppBar.kt index c5f07c4093..daced9fb93 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupTopAppBar.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/AccountTopAppBar.kt @@ -1,22 +1,25 @@ -package app.k9mail.feature.account.setup.ui.common +package app.k9mail.feature.account.common.ui import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import app.k9mail.core.ui.compose.common.DevicePreviews import app.k9mail.core.ui.compose.designsystem.organism.TopAppBar import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.MainTheme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme -import app.k9mail.feature.account.setup.R.string +import app.k9mail.feature.account.common.R @Composable -internal fun AccountSetupTopAppBar( +fun AccountTopAppBar( title: String, + modifier: Modifier = Modifier, ) { TopAppBar( title = title, - subtitle = stringResource(id = string.account_setup_title), + modifier = modifier, + subtitle = stringResource(id = R.string.account_common_title), titleContentPadding = PaddingValues( start = MainTheme.spacings.double, ), @@ -25,9 +28,9 @@ internal fun AccountSetupTopAppBar( @DevicePreviews @Composable -internal fun AccountSetupTopAppBarK9Preview() { +internal fun AccountTopAppBarK9Preview() { K9Theme { - AccountSetupTopAppBar( + AccountTopAppBar( title = "Title", ) } @@ -35,9 +38,9 @@ internal fun AccountSetupTopAppBarK9Preview() { @DevicePreviews @Composable -internal fun AccountSetupTopAppBarThunderbirdPreview() { +internal fun AccountTopAppBarThunderbirdPreview() { ThunderbirdTheme { - AccountSetupTopAppBar( + AccountTopAppBar( title = "Title", ) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt index 7d0d5de668..f512ee48db 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt @@ -10,10 +10,10 @@ import app.k9mail.core.ui.compose.common.mvi.observe import app.k9mail.core.ui.compose.designsystem.template.Scaffold import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme +import app.k9mail.feature.account.common.ui.AccountTopAppBar import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.ui.common.AccountSetupTopAppBar import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.ViewModel @@ -42,7 +42,7 @@ internal fun AccountIncomingConfigScreen( Scaffold( topBar = { - AccountSetupTopAppBar( + AccountTopAppBar( title = stringResource(id = R.string.account_setup_incoming_config_top_bar_title), ) }, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt index 6c89bcb20d..999ffea1da 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt @@ -10,10 +10,10 @@ import app.k9mail.core.ui.compose.common.mvi.observe import app.k9mail.core.ui.compose.designsystem.template.Scaffold import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme +import app.k9mail.feature.account.common.ui.AccountTopAppBar import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.setup.R.string -import app.k9mail.feature.account.setup.ui.common.AccountSetupTopAppBar import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.Effect import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.Event import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract.ViewModel @@ -42,7 +42,7 @@ internal fun AccountOptionsScreen( Scaffold( topBar = { - AccountSetupTopAppBar( + AccountTopAppBar( title = stringResource(id = string.account_setup_options_top_bar_title), ) }, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt index 279a79e9d4..c045b1531a 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt @@ -10,10 +10,10 @@ import app.k9mail.core.ui.compose.common.mvi.observe import app.k9mail.core.ui.compose.designsystem.template.Scaffold import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme +import app.k9mail.feature.account.common.ui.AccountTopAppBar import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.ui.common.AccountSetupTopAppBar import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.ViewModel @@ -42,7 +42,7 @@ internal fun AccountOutgoingConfigScreen( Scaffold( topBar = { - AccountSetupTopAppBar( + AccountTopAppBar( title = stringResource(id = R.string.account_setup_outgoing_config_top_bar_title), ) }, -- GitLab From fb02e39f9116045b8f2e939d143d7003dfcd39cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 12:05:34 +0200 Subject: [PATCH 17/94] Remove back and next button texts on WizardNavigationBar as they have default values set already --- .../feature/account/common/ui/WizardNavigationBar.kt | 10 ---------- .../ui/autodiscovery/AccountAutoDiscoveryScreen.kt | 2 -- .../setup/ui/incoming/AccountIncomingConfigScreen.kt | 2 -- .../account/setup/ui/options/AccountOptionsScreen.kt | 1 - .../setup/ui/outgoing/AccountOutgoingConfigScreen.kt | 2 -- feature/account/setup/src/main/res/values/strings.xml | 2 -- 6 files changed, 19 deletions(-) diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/WizardNavigationBar.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/WizardNavigationBar.kt index fb5d1fd7c9..1f50e2884b 100644 --- a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/WizardNavigationBar.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/WizardNavigationBar.kt @@ -74,8 +74,6 @@ private fun getHorizontalArrangement(state: WizardNavigationBarState): Arrangeme internal fun WizardNavigationBarK9Preview() { K9Theme { WizardNavigationBar( - nextButtonText = "Next", - backButtonText = "Back", onNextClick = {}, onBackClick = {}, ) @@ -87,8 +85,6 @@ internal fun WizardNavigationBarK9Preview() { internal fun WizardNavigationBarPreview() { PreviewWithThemes { WizardNavigationBar( - nextButtonText = "Next", - backButtonText = "Back", onNextClick = {}, onBackClick = {}, ) @@ -100,8 +96,6 @@ internal fun WizardNavigationBarPreview() { internal fun WizardNavigationBarDisabledPreview() { PreviewWithThemes { WizardNavigationBar( - nextButtonText = "Next", - backButtonText = "Back", onNextClick = {}, onBackClick = {}, state = WizardNavigationBarState( @@ -117,8 +111,6 @@ internal fun WizardNavigationBarDisabledPreview() { internal fun WizardNavigationBarHideNextPreview() { PreviewWithThemes { WizardNavigationBar( - nextButtonText = "Next", - backButtonText = "Back", onNextClick = {}, onBackClick = {}, state = WizardNavigationBarState( @@ -133,8 +125,6 @@ internal fun WizardNavigationBarHideNextPreview() { internal fun WizardNavigationBarHideBackPreview() { PreviewWithThemes { WizardNavigationBar( - nextButtonText = "Next", - backButtonText = "Back", onNextClick = {}, onBackClick = {}, state = WizardNavigationBarState( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryScreen.kt index 174e00ba75..d5fd3ab63b 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryScreen.kt @@ -46,8 +46,6 @@ internal fun AccountAutoDiscoveryScreen( }, bottomBar = { WizardNavigationBar( - nextButtonText = stringResource(id = R.string.account_setup_button_next), - backButtonText = stringResource(id = R.string.account_setup_button_back), onNextClick = { dispatch(Event.OnNextClicked) }, onBackClick = { dispatch(Event.OnBackClicked) }, state = WizardNavigationBarState(showNext = state.value.isNextButtonVisible), diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt index f512ee48db..aba49a064f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt @@ -48,8 +48,6 @@ internal fun AccountIncomingConfigScreen( }, bottomBar = { WizardNavigationBar( - nextButtonText = stringResource(id = R.string.account_setup_button_next), - backButtonText = stringResource(id = R.string.account_setup_button_back), onNextClick = { dispatch(Event.OnNextClicked) }, onBackClick = { dispatch(Event.OnBackClicked) }, ) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt index 999ffea1da..edd2fd31fc 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsScreen.kt @@ -49,7 +49,6 @@ internal fun AccountOptionsScreen( bottomBar = { WizardNavigationBar( nextButtonText = stringResource(id = string.account_setup_button_finish), - backButtonText = stringResource(id = string.account_setup_button_back), onNextClick = { dispatch(Event.OnNextClicked) }, onBackClick = { dispatch(Event.OnBackClicked) }, ) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt index c045b1531a..e1c184633c 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt @@ -48,8 +48,6 @@ internal fun AccountOutgoingConfigScreen( }, bottomBar = { WizardNavigationBar( - nextButtonText = stringResource(id = R.string.account_setup_button_next), - backButtonText = stringResource(id = R.string.account_setup_button_back), onNextClick = { dispatch(Event.OnNextClicked) }, onBackClick = { dispatch(Event.OnBackClicked) }, ) diff --git a/feature/account/setup/src/main/res/values/strings.xml b/feature/account/setup/src/main/res/values/strings.xml index 7197bcb058..19e84d79c8 100644 --- a/feature/account/setup/src/main/res/values/strings.xml +++ b/feature/account/setup/src/main/res/values/strings.xml @@ -1,8 +1,6 @@ K-9 Mail - Next - Back Finish None SSL/TLS -- GitLab From f14121484494ba3970c0ab61d7beca06e9088153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 12:39:41 +0200 Subject: [PATCH 18/94] Move domain entities to account common module --- .../domain/entity/AuthenticationType.kt | 2 +- .../domain/entity/ConnectionSecurity.kt | 19 ++++++++------- .../domain/entity/IncomingProtocolType.kt | 4 ++-- .../domain/entity/OutgoingProtocolType.kt | 6 ++--- .../common/domain/entity/AccountStateTest.kt | 23 +++++++++++++++++++ .../domain/entity/AuthenticationTypeTest.kt | 2 +- .../domain/entity/AuthorizationStateTest.kt | 15 ++++++++++++ .../domain/entity/ConnectionSecurityTest.kt | 3 +-- .../domain/entity/IncomingProtocolTypeTest.kt | 2 +- .../domain/entity/OutgoingProtocolTypeTest.kt | 2 +- .../setup/domain/AutoDiscoveryMapper.kt | 4 ++-- .../entity/AutoDiscoveryAuthenticationType.kt | 2 ++ .../entity/AutoDiscoveryConnectionSecurity.kt | 2 ++ .../entity/IncomingServerSettingsExtension.kt | 1 + .../ui/common/AccountSetupStringMapper.kt | 2 +- .../mapper/AuthenticationTypeStringMapper.kt | 2 +- .../incoming/AccountIncomingConfigContent.kt | 4 ++-- .../incoming/AccountIncomingConfigContract.kt | 8 +++---- .../AccountIncomingConfigStateExtensions.kt | 22 ++++++++---------- .../AccountIncomingConfigStateMapper.kt | 10 ++++---- .../AccountIncomingConfigViewModel.kt | 6 ++--- .../outgoing/AccountOutgoingConfigContent.kt | 4 ++-- .../outgoing/AccountOutgoingConfigContract.kt | 6 ++--- .../AccountOutgoingConfigStateMapper.kt | 8 +++---- .../AccountOutgoingConfigViewModel.kt | 4 ++-- .../AutoDiscoveryAuthenticationTypeKtTest.kt | 1 + .../AutoDiscoveryConnectionSecurityKtTest.kt | 1 + .../IncomingServerSettingsExtensionKtTest.kt | 1 + .../AccountAutoDiscoveryStateMapperKtTest.kt | 4 ++-- .../AccountIncomingConfigStateMapperKtTest.kt | 6 ++--- .../AccountIncomingConfigStateTest.kt | 8 +++---- .../AccountIncomingConfigViewModelTest.kt | 10 ++++---- .../AccountOutgoingConfigStateMapperKtTest.kt | 4 ++-- .../AccountOutgoingConfigStateTest.kt | 6 ++--- .../AccountOutgoingConfigViewModelTest.kt | 6 ++--- 35 files changed, 125 insertions(+), 85 deletions(-) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/entity/AuthenticationType.kt (96%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/entity/ConnectionSecurity.kt (58%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/entity/IncomingProtocolType.kt (83%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => common/src/main/kotlin/app/k9mail/feature/account/common}/domain/entity/OutgoingProtocolType.kt (68%) create mode 100644 feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AccountStateTest.kt rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => common/src/test/kotlin/app/k9mail/feature/account/common}/domain/entity/AuthenticationTypeTest.kt (96%) create mode 100644 feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AuthorizationStateTest.kt rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => common/src/test/kotlin/app/k9mail/feature/account/common}/domain/entity/ConnectionSecurityTest.kt (95%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => common/src/test/kotlin/app/k9mail/feature/account/common}/domain/entity/IncomingProtocolTypeTest.kt (96%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => common/src/test/kotlin/app/k9mail/feature/account/common}/domain/entity/OutgoingProtocolTypeTest.kt (95%) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AuthenticationType.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AuthenticationType.kt similarity index 96% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AuthenticationType.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AuthenticationType.kt index 77591f7956..c6965b2356 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AuthenticationType.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AuthenticationType.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity import com.fsck.k9.mail.AuthType import kotlinx.collections.immutable.toImmutableList diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurity.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/ConnectionSecurity.kt similarity index 58% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurity.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/ConnectionSecurity.kt index d9a44316bd..0696af5afc 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurity.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/ConnectionSecurity.kt @@ -1,9 +1,8 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity -import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity.None -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity.StartTLS -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity.TLS +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity.None +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity.StartTLS +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity.TLS import kotlinx.collections.immutable.toImmutableList enum class ConnectionSecurity { @@ -18,7 +17,7 @@ enum class ConnectionSecurity { } } -internal fun ConnectionSecurity.toMailConnectionSecurity(): MailConnectionSecurity { +fun ConnectionSecurity.toMailConnectionSecurity(): MailConnectionSecurity { return when (this) { None -> MailConnectionSecurity.NONE StartTLS -> MailConnectionSecurity.STARTTLS_REQUIRED @@ -26,7 +25,7 @@ internal fun ConnectionSecurity.toMailConnectionSecurity(): MailConnectionSecuri } } -internal fun MailConnectionSecurity.toConnectionSecurity(): ConnectionSecurity { +fun MailConnectionSecurity.toConnectionSecurity(): ConnectionSecurity { return when (this) { MailConnectionSecurity.NONE -> None MailConnectionSecurity.STARTTLS_REQUIRED -> StartTLS @@ -35,7 +34,7 @@ internal fun MailConnectionSecurity.toConnectionSecurity(): ConnectionSecurity { } @Suppress("MagicNumber") -internal fun ConnectionSecurity.toSmtpDefaultPort(): Long { +fun ConnectionSecurity.toSmtpDefaultPort(): Long { return when (this) { None -> 587 StartTLS -> 587 @@ -44,7 +43,7 @@ internal fun ConnectionSecurity.toSmtpDefaultPort(): Long { } @Suppress("MagicNumber") -internal fun ConnectionSecurity.toImapDefaultPort(): Long { +fun ConnectionSecurity.toImapDefaultPort(): Long { return when (this) { None -> 143 StartTLS -> 143 @@ -53,7 +52,7 @@ internal fun ConnectionSecurity.toImapDefaultPort(): Long { } @Suppress("MagicNumber") -internal fun ConnectionSecurity.toPop3DefaultPort(): Long { +fun ConnectionSecurity.toPop3DefaultPort(): Long { return when (this) { None -> 110 StartTLS -> 110 diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingProtocolType.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/IncomingProtocolType.kt similarity index 83% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingProtocolType.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/IncomingProtocolType.kt index cc245cecd2..62545c1ca0 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingProtocolType.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/IncomingProtocolType.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity import kotlinx.collections.immutable.toImmutableList @@ -21,7 +21,7 @@ enum class IncomingProtocolType( } } -internal fun IncomingProtocolType.toDefaultPort(connectionSecurity: ConnectionSecurity): Long { +fun IncomingProtocolType.toDefaultPort(connectionSecurity: ConnectionSecurity): Long { return when (this) { IncomingProtocolType.IMAP -> connectionSecurity.toImapDefaultPort() IncomingProtocolType.POP3 -> connectionSecurity.toPop3DefaultPort() diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/OutgoingProtocolType.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/OutgoingProtocolType.kt similarity index 68% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/OutgoingProtocolType.kt rename to feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/OutgoingProtocolType.kt index c90cde0aba..e59b81a7fa 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/OutgoingProtocolType.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/OutgoingProtocolType.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity import kotlinx.collections.immutable.toImmutableList -internal enum class OutgoingProtocolType( +enum class OutgoingProtocolType( val defaultName: String, val defaultConnectionSecurity: ConnectionSecurity, ) { @@ -16,7 +16,7 @@ internal enum class OutgoingProtocolType( } } -internal fun OutgoingProtocolType.toDefaultPort(connectionSecurity: ConnectionSecurity): Long { +fun OutgoingProtocolType.toDefaultPort(connectionSecurity: ConnectionSecurity): Long { return when (this) { OutgoingProtocolType.SMTP -> connectionSecurity.toSmtpDefaultPort() } diff --git a/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AccountStateTest.kt b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AccountStateTest.kt new file mode 100644 index 0000000000..dd3c0c4e97 --- /dev/null +++ b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AccountStateTest.kt @@ -0,0 +1,23 @@ +package app.k9mail.feature.account.common.domain.entity + +import assertk.all +import assertk.assertThat +import assertk.assertions.isNull +import assertk.assertions.prop +import org.junit.Test + +class AccountStateTest { + + @Test + fun `should default to null state`() { + val accountState = AccountState() + + assertThat(accountState).all { + prop(AccountState::emailAddress).isNull() + prop(AccountState::incomingServerSettings).isNull() + prop(AccountState::outgoingServerSettings).isNull() + prop(AccountState::authorizationState).isNull() + prop(AccountState::options).isNull() + } + } +} diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AuthenticationTypeTest.kt b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AuthenticationTypeTest.kt similarity index 96% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AuthenticationTypeTest.kt rename to feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AuthenticationTypeTest.kt index 72dc059261..f7f3449927 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AuthenticationTypeTest.kt +++ b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AuthenticationTypeTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AuthorizationStateTest.kt b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AuthorizationStateTest.kt new file mode 100644 index 0000000000..1311b66076 --- /dev/null +++ b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/AuthorizationStateTest.kt @@ -0,0 +1,15 @@ +package app.k9mail.feature.account.common.domain.entity + +import assertk.assertThat +import assertk.assertions.isNull +import org.junit.Test + +class AuthorizationStateTest { + + @Test + fun `should default to null state`() { + val authorizationState = AuthorizationState() + + assertThat(authorizationState.state).isNull() + } +} diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurityTest.kt b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/ConnectionSecurityTest.kt similarity index 95% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurityTest.kt rename to feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/ConnectionSecurityTest.kt index 64de5d12fe..4cdc873c10 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/ConnectionSecurityTest.kt +++ b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/ConnectionSecurityTest.kt @@ -1,6 +1,5 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity -import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingProtocolTypeTest.kt b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/IncomingProtocolTypeTest.kt similarity index 96% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingProtocolTypeTest.kt rename to feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/IncomingProtocolTypeTest.kt index d10da4c8fa..9966eb14a3 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingProtocolTypeTest.kt +++ b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/IncomingProtocolTypeTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/OutgoingProtocolTypeTest.kt b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/OutgoingProtocolTypeTest.kt similarity index 95% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/OutgoingProtocolTypeTest.kt rename to feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/OutgoingProtocolTypeTest.kt index 33afc43d1a..15dca7520c 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/OutgoingProtocolTypeTest.kt +++ b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/domain/entity/OutgoingProtocolTypeTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.entity +package app.k9mail.feature.account.common.domain.entity import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/AutoDiscoveryMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/AutoDiscoveryMapper.kt index cc99e9eee3..6291e02dde 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/AutoDiscoveryMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/AutoDiscoveryMapper.kt @@ -4,10 +4,10 @@ import app.k9mail.autodiscovery.api.ImapServerSettings import app.k9mail.autodiscovery.api.IncomingServerSettings import app.k9mail.autodiscovery.api.OutgoingServerSettings import app.k9mail.autodiscovery.api.SmtpServerSettings -import app.k9mail.feature.account.setup.domain.entity.toAuthType +import app.k9mail.feature.account.common.domain.entity.toAuthType +import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.toMailConnectionSecurity import com.fsck.k9.mail.ServerSettings internal fun IncomingServerSettings.toServerSettings(password: String?): ServerSettings { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryAuthenticationType.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryAuthenticationType.kt index a6c2e0be7e..ae50f9885f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryAuthenticationType.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryAuthenticationType.kt @@ -1,5 +1,7 @@ package app.k9mail.feature.account.setup.domain.entity +import app.k9mail.feature.account.common.domain.entity.AuthenticationType + typealias AutoDiscoveryAuthenticationType = app.k9mail.autodiscovery.api.AuthenticationType internal fun AutoDiscoveryAuthenticationType.toAuthenticationType(): AuthenticationType { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryConnectionSecurity.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryConnectionSecurity.kt index 8405582849..a5b480ece0 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryConnectionSecurity.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryConnectionSecurity.kt @@ -1,5 +1,7 @@ package app.k9mail.feature.account.setup.domain.entity +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity + internal typealias AutoDiscoveryConnectionSecurity = app.k9mail.autodiscovery.api.ConnectionSecurity internal fun AutoDiscoveryConnectionSecurity.toConnectionSecurity(): ConnectionSecurity { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingServerSettingsExtension.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingServerSettingsExtension.kt index f45819e1ad..646b71d914 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingServerSettingsExtension.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingServerSettingsExtension.kt @@ -2,6 +2,7 @@ package app.k9mail.feature.account.setup.domain.entity import app.k9mail.autodiscovery.api.ImapServerSettings import app.k9mail.autodiscovery.api.IncomingServerSettings +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType internal fun IncomingServerSettings.toIncomingProtocolType(): IncomingProtocolType { when (this) { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupStringMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupStringMapper.kt index 15b40d767a..3632e43d1b 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupStringMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupStringMapper.kt @@ -2,8 +2,8 @@ package app.k9mail.feature.account.setup.ui.common import android.content.res.Resources import app.k9mail.core.common.domain.usecase.validation.ValidationError +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError import app.k9mail.feature.account.setup.domain.usecase.ValidateImapPrefix.ValidateImapPrefixError import app.k9mail.feature.account.setup.domain.usecase.ValidatePassword.ValidatePasswordError diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/mapper/AuthenticationTypeStringMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/mapper/AuthenticationTypeStringMapper.kt index cc6e28ce9c..5ec5ebebee 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/mapper/AuthenticationTypeStringMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/mapper/AuthenticationTypeStringMapper.kt @@ -1,8 +1,8 @@ package app.k9mail.feature.account.setup.ui.common.mapper import android.content.res.Resources +import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType internal fun AuthenticationType.toResourceString(resources: Resources): String { return when (this) { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContent.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContent.kt index 620c230a6c..2cd1a405cf 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContent.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContent.kt @@ -25,10 +25,10 @@ import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.MainTheme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.ui.item.defaultItemPadding import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType import app.k9mail.feature.account.setup.ui.clientcertificate.ClientCertificateInput import app.k9mail.feature.account.setup.ui.common.mapper.toResourceString import app.k9mail.feature.account.setup.ui.common.toResourceString diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt index 1a73dc68b9..4be0fdc556 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt @@ -2,12 +2,12 @@ package app.k9mail.feature.account.setup.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType +import app.k9mail.feature.account.common.domain.entity.toDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType -import app.k9mail.feature.account.setup.domain.entity.toDefaultPort interface AccountIncomingConfigContract { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateExtensions.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateExtensions.kt index 9956324bf8..d586bcc803 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateExtensions.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateExtensions.kt @@ -1,11 +1,7 @@ package app.k9mail.feature.account.setup.ui.incoming -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType.ClientCertificate -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType.OAuth2 -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType.PasswordCleartext -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType.PasswordEncrypted -import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList @@ -19,18 +15,18 @@ internal val IncomingProtocolType.allowedAuthenticationTypes: List { listOf( - PasswordCleartext, - PasswordEncrypted, - ClientCertificate, - OAuth2, + AuthenticationType.PasswordCleartext, + AuthenticationType.PasswordEncrypted, + AuthenticationType.ClientCertificate, + AuthenticationType.OAuth2, ) } IncomingProtocolType.POP3 -> { listOf( - PasswordCleartext, - PasswordEncrypted, - ClientCertificate, + AuthenticationType.PasswordCleartext, + AuthenticationType.PasswordEncrypted, + AuthenticationType.ClientCertificate, ) } } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt index 3d3285e15f..95f5f5fdac 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt @@ -1,13 +1,13 @@ package app.k9mail.feature.account.setup.ui.incoming import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType +import app.k9mail.feature.account.common.domain.entity.toAuthType +import app.k9mail.feature.account.common.domain.entity.toAuthenticationType +import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType -import app.k9mail.feature.account.setup.domain.entity.toAuthType -import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType -import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.store.imap.ImapStoreSettings diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt index e0ee4960dd..647faf3512 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt @@ -3,9 +3,9 @@ package app.k9mail.feature.account.setup.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.common.domain.AccountDomainContract -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType -import app.k9mail.feature.account.setup.domain.entity.toDefaultPort +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType +import app.k9mail.feature.account.common.domain.entity.toDefaultPort import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContent.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContent.kt index ea9bd3bcbc..1debb3fe3d 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContent.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContent.kt @@ -24,10 +24,10 @@ import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.MainTheme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.ui.item.defaultItemPadding import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.ui.clientcertificate.ClientCertificateInput import app.k9mail.feature.account.setup.ui.common.mapper.toResourceString import app.k9mail.feature.account.setup.ui.common.toResourceString diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt index b1c83e27de..29b50f318e 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt @@ -2,11 +2,11 @@ package app.k9mail.feature.account.setup.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.toSmtpDefaultPort interface AccountOutgoingConfigContract { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt index 15f477c345..1a4ac97455 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt @@ -1,12 +1,12 @@ package app.k9mail.feature.account.setup.ui.outgoing import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.toAuthType +import app.k9mail.feature.account.common.domain.entity.toAuthenticationType +import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.toAuthType -import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType -import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State import com.fsck.k9.mail.ServerSettings diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt index 9e10d344b7..a01369ec5e 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt @@ -3,8 +3,8 @@ package app.k9mail.feature.account.setup.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.common.domain.AccountDomainContract -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.toSmtpDefaultPort +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryAuthenticationTypeKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryAuthenticationTypeKtTest.kt index 9f71df2605..47e0504332 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryAuthenticationTypeKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryAuthenticationTypeKtTest.kt @@ -1,5 +1,6 @@ package app.k9mail.feature.account.setup.domain.entity +import app.k9mail.feature.account.common.domain.entity.AuthenticationType import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryConnectionSecurityKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryConnectionSecurityKtTest.kt index 0901951aab..31d112a202 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryConnectionSecurityKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/AutoDiscoveryConnectionSecurityKtTest.kt @@ -1,5 +1,6 @@ package app.k9mail.feature.account.setup.domain.entity +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingServerSettingsExtensionKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingServerSettingsExtensionKtTest.kt index 89206a0f2c..66585646bc 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingServerSettingsExtensionKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/entity/IncomingServerSettingsExtensionKtTest.kt @@ -4,6 +4,7 @@ import app.k9mail.autodiscovery.api.AuthenticationType import app.k9mail.autodiscovery.api.ImapServerSettings import app.k9mail.core.common.net.toHostname import app.k9mail.core.common.net.toPort +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt index 1fa7237794..0f144be8a6 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt @@ -6,12 +6,12 @@ import app.k9mail.autodiscovery.api.SmtpServerSettings import app.k9mail.core.common.net.toHostname import app.k9mail.core.common.net.toPort import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt index 93a53158a7..f56740d48f 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt @@ -1,11 +1,11 @@ package app.k9mail.feature.account.setup.ui.incoming +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt index 1b0120efcb..6a05191532 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt @@ -1,11 +1,11 @@ package app.k9mail.feature.account.setup.ui.incoming +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType +import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType -import app.k9mail.feature.account.setup.domain.entity.toImapDefaultPort import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt index b0568ad9d1..d470f1284a 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt @@ -10,14 +10,14 @@ import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort +import app.k9mail.feature.account.common.domain.entity.toPop3DefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.IncomingProtocolType -import app.k9mail.feature.account.setup.domain.entity.toImapDefaultPort -import app.k9mail.feature.account.setup.domain.entity.toPop3DefaultPort import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt index dfb1461c12..a6394e6f86 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt @@ -1,10 +1,10 @@ package app.k9mail.feature.account.setup.ui.outgoing +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt index f9328447af..0ae7ac7faf 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt @@ -1,10 +1,10 @@ package app.k9mail.feature.account.setup.ui.outgoing +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt index 1945c902bc..31c3f8fc45 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt @@ -10,12 +10,12 @@ import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State -- GitLab From 4f2fe9f6e56a946ee5ccdb824433559abf8041f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 13:41:03 +0200 Subject: [PATCH 19/94] Move server config to its own module --- .../account/server/config/build.gradle.kts | 29 +++++++++ .../server/config/ServerConfigModule.kt | 30 ++++++++++ .../domain/ServerConfigDomainContract.kt | 33 ++++++++++ .../domain/usecase/ValidateEmailAddress.kt | 6 +- .../domain/usecase/ValidateImapPrefix.kt | 6 +- .../domain/usecase/ValidatePassword.kt | 6 +- .../config}/domain/usecase/ValidatePort.kt | 6 +- .../config}/domain/usecase/ValidateServer.kt | 6 +- .../domain/usecase/ValidateUsername.kt | 6 +- .../ui/common}/ClientCertificateInput.kt | 6 +- .../mapper/AuthenticationTypeStringMapper.kt | 29 +++++++++ .../mapper/ConnectionSecurityStringMapper.kt | 13 ++++ .../mapper/ValidationErrorStringMapper.kt} | 43 ++++++------- .../incoming/AccountIncomingConfigContent.kt | 37 ++++++------ .../incoming/AccountIncomingConfigContract.kt | 2 +- .../incoming/AccountIncomingConfigScreen.kt | 14 ++--- .../AccountIncomingConfigStateExtensions.kt | 2 +- .../AccountIncomingConfigStateMapper.kt | 4 +- .../AccountIncomingConfigValidator.kt | 14 ++--- .../AccountIncomingConfigViewModel.kt | 14 ++--- .../FakeAccountIncomingConfigValidator.kt | 3 +- .../FakeAccountIncomingConfigViewModel.kt | 22 +++++++ .../outgoing/AccountOutgoingConfigContent.kt | 25 ++++---- .../outgoing/AccountOutgoingConfigContract.kt | 2 +- .../outgoing/AccountOutgoingConfigScreen.kt | 14 ++--- .../AccountOutgoingConfigStateExtensions.kt | 2 +- .../AccountOutgoingConfigStateMapper.kt | 4 +- .../AccountOutgoingConfigValidator.kt | 10 ++-- .../AccountOutgoingConfigViewModel.kt | 14 ++--- .../FakeAccountOutgoingConfigValidator.kt | 3 +- .../FakeAccountOutgoingConfigViewModel.kt | 22 +++++++ .../config/src/main/res/values/strings.xml | 40 +++++++++++++ .../usecase/ValidateEmailAddressTest.kt | 4 +- .../domain/usecase/ValidateImapPrefixTest.kt | 2 +- .../domain/usecase/ValidatePasswordTest.kt | 2 +- .../domain/usecase/ValidatePortTest.kt | 4 +- .../domain/usecase/ValidateServerTest.kt | 2 +- .../domain/usecase/ValidateUsernameTest.kt | 2 +- .../AccountIncomingConfigScreenKtTest.kt | 7 ++- .../AccountIncomingConfigStateMapperKtTest.kt | 4 +- .../AccountIncomingConfigStateTest.kt | 4 +- .../AccountIncomingConfigViewModelTest.kt | 9 +-- .../AccountOutgoingConfigScreenKtTest.kt | 7 ++- .../AccountOutgoingConfigStateMapperKtTest.kt | 4 +- .../AccountOutgoingConfigStateTest.kt | 4 +- .../AccountOutgoingConfigViewModelTest.kt | 9 +-- feature/account/setup/build.gradle.kts | 1 + .../account/setup/AccountSetupModule.kt | 23 +------ .../account/setup/domain/DomainContract.kt | 29 --------- .../account/setup/ui/AccountSetupScreen.kt | 12 ++-- .../AccountAutoDiscoveryContent.kt | 4 +- .../AccountAutoDiscoveryStateMapper.kt | 4 +- .../AccountAutoDiscoveryValidator.kt | 9 +-- .../AutoDiscoveryStringMapper.kt | 6 +- .../ui/autodiscovery/item/EmailAddressItem.kt | 2 +- .../ui/autodiscovery/item/PasswordItem.kt | 2 +- .../view/AutoDiscoveryServerSettingsView.kt | 1 - .../view/AutoDiscoveryStatusBodyView.kt | 4 +- .../view/AutoDiscoveryStatusHeaderState.kt | 12 ++-- .../view/ConfigurationApprovalView.kt | 2 +- .../mapper/AuthenticationTypeStringMapper.kt | 25 -------- .../setup/src/main/res/values/strings.xml | 60 ++++--------------- .../account/setup/AccountSetupModuleKtTest.kt | 4 +- .../setup/ui/AccountSetupScreenKtTest.kt | 4 +- .../AccountAutoDiscoveryStateMapperKtTest.kt | 4 +- .../FakeAccountIncomingConfigViewModel.kt | 22 ------- .../FakeAccountOutgoingConfigViewModel.kt | 22 ------- settings.gradle.kts | 1 + 68 files changed, 424 insertions(+), 360 deletions(-) create mode 100644 feature/account/server/config/build.gradle.kts create mode 100644 feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ServerConfigModule.kt create mode 100644 feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/ServerConfigDomainContract.kt rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidateEmailAddress.kt (82%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidateImapPrefix.kt (72%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidatePassword.kt (74%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidatePort.kt (78%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidateServer.kt (71%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidateUsername.kt (70%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/clientcertificate => server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common}/ClientCertificateInput.kt (85%) create mode 100644 feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/AuthenticationTypeStringMapper.kt create mode 100644 feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ConnectionSecurityStringMapper.kt rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupStringMapper.kt => server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ValidationErrorStringMapper.kt} (52%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigContent.kt (89%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigContract.kt (98%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigScreen.kt (82%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigStateExtensions.kt (95%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigStateMapper.kt (94%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigValidator.kt (68%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigViewModel.kt (89%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming => server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake}/FakeAccountIncomingConfigValidator.kt (86%) create mode 100644 feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigContent.kt (89%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigContract.kt (97%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigScreen.kt (82%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigStateExtensions.kt (81%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigStateMapper.kt (92%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigValidator.kt (71%) rename feature/account/{setup/src/main/kotlin/app/k9mail/feature/account/setup => server/config/src/main/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigViewModel.kt (85%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing => server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake}/FakeAccountOutgoingConfigValidator.kt (83%) create mode 100644 feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt create mode 100644 feature/account/server/config/src/main/res/values/strings.xml rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidateEmailAddressTest.kt (86%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidateImapPrefixTest.kt (93%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidatePasswordTest.kt (94%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidatePortTest.kt (91%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidateServerTest.kt (94%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/domain/usecase/ValidateUsernameTest.kt (94%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigScreenKtTest.kt (76%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt (95%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigStateTest.kt (89%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/ui/incoming/AccountIncomingConfigViewModelTest.kt (97%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt (76%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt (90%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigStateTest.kt (87%) rename feature/account/{setup/src/test/kotlin/app/k9mail/feature/account/setup => server/config/src/test/kotlin/app/k9mail/feature/account/server/config}/ui/outgoing/AccountOutgoingConfigViewModelTest.kt (96%) delete mode 100644 feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/mapper/AuthenticationTypeStringMapper.kt delete mode 100644 feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/FakeAccountIncomingConfigViewModel.kt delete mode 100644 feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/FakeAccountOutgoingConfigViewModel.kt diff --git a/feature/account/server/config/build.gradle.kts b/feature/account/server/config/build.gradle.kts new file mode 100644 index 0000000000..1adbc030a0 --- /dev/null +++ b/feature/account/server/config/build.gradle.kts @@ -0,0 +1,29 @@ +plugins { + id(ThunderbirdPlugins.Library.androidCompose) +} + +android { + namespace = "app.k9mail.feature.account.server.config" + resourcePrefix = "account_server_config_" + + buildTypes { + debug { + manifestPlaceholders["appAuthRedirectScheme"] = "FIXME: override this in your app project" + } + release { + manifestPlaceholders["appAuthRedirectScheme"] = "FIXME: override this in your app project" + } + } +} + +dependencies { + implementation(projects.core.ui.compose.designsystem) + implementation(projects.core.common) + + implementation(projects.mail.common) + implementation(projects.mail.protocols.imap) + + implementation(projects.feature.account.common) + + testImplementation(projects.core.ui.compose.testing) +} diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ServerConfigModule.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ServerConfigModule.kt new file mode 100644 index 0000000000..5b3ed5345b --- /dev/null +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ServerConfigModule.kt @@ -0,0 +1,30 @@ +package app.k9mail.feature.account.server.config + +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigValidator +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigViewModel +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigValidator +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigViewModel +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.core.module.Module +import org.koin.dsl.module + +val featureAccountServerConfigModule: Module = module { + factory { AccountIncomingConfigValidator() } + factory { AccountOutgoingConfigValidator() } + + viewModel { + AccountIncomingConfigViewModel( + validator = get(), + accountStateRepository = get(), + ) + } + + viewModel { + AccountOutgoingConfigViewModel( + validator = get(), + accountStateRepository = get(), + ) + } +} diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/ServerConfigDomainContract.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/ServerConfigDomainContract.kt new file mode 100644 index 0000000000..ce9dc8bfb9 --- /dev/null +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/ServerConfigDomainContract.kt @@ -0,0 +1,33 @@ +package app.k9mail.feature.account.server.config.domain + +import app.k9mail.core.common.domain.usecase.validation.ValidationResult + +interface ServerConfigDomainContract { + + interface UseCase { + + fun interface ValidateEmailAddress { + fun execute(emailAddress: String): ValidationResult + } + + fun interface ValidatePassword { + fun execute(password: String): ValidationResult + } + + fun interface ValidateServer { + fun execute(server: String): ValidationResult + } + + fun interface ValidatePort { + fun execute(port: Long?): ValidationResult + } + + fun interface ValidateUsername { + fun execute(username: String): ValidationResult + } + + fun interface ValidateImapPrefix { + fun execute(imapPrefix: String): ValidationResult + } + } +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddress.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddress.kt similarity index 82% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddress.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddress.kt index b53451a621..c33f224e1c 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddress.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddress.kt @@ -1,10 +1,10 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase -internal class ValidateEmailAddress : DomainContract.UseCase.ValidateEmailAddress { +class ValidateEmailAddress : UseCase.ValidateEmailAddress { // TODO replace by new email validation override fun execute(emailAddress: String): ValidationResult { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateImapPrefix.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefix.kt similarity index 72% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateImapPrefix.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefix.kt index 486d072583..43845b0894 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateImapPrefix.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefix.kt @@ -1,10 +1,10 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase -internal class ValidateImapPrefix : DomainContract.UseCase.ValidateImapPrefix { +internal class ValidateImapPrefix : UseCase.ValidateImapPrefix { override fun execute(imapPrefix: String): ValidationResult { return when { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePassword.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePassword.kt similarity index 74% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePassword.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePassword.kt index f7c2548322..b0a95b4c82 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePassword.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePassword.kt @@ -1,10 +1,10 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase -internal class ValidatePassword : DomainContract.UseCase.ValidatePassword { +class ValidatePassword : UseCase.ValidatePassword { // TODO change behavior to allow empty password when no password is required based on auth type override fun execute(password: String): ValidationResult { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePort.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePort.kt similarity index 78% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePort.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePort.kt index f0e31b67b8..30288f24c6 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePort.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePort.kt @@ -1,10 +1,10 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase -internal class ValidatePort : DomainContract.UseCase.ValidatePort { +internal class ValidatePort : UseCase.ValidatePort { override fun execute(port: Long?): ValidationResult { return when (port) { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServer.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServer.kt similarity index 71% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServer.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServer.kt index 31fcfb63df..7fbe43c7a4 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServer.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServer.kt @@ -1,10 +1,10 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase -internal class ValidateServer : DomainContract.UseCase.ValidateServer { +internal class ValidateServer : UseCase.ValidateServer { // TODO validate domain, ip4 or ip6 override fun execute(server: String): ValidationResult { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateUsername.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsername.kt similarity index 70% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateUsername.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsername.kt index 7399330bb7..c83482cbd2 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateUsername.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsername.kt @@ -1,10 +1,10 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.setup.domain.DomainContract +import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase -internal class ValidateUsername : DomainContract.UseCase.ValidateUsername { +internal class ValidateUsername : UseCase.ValidateUsername { override fun execute(username: String): ValidationResult { return when { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/clientcertificate/ClientCertificateInput.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/ClientCertificateInput.kt similarity index 85% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/clientcertificate/ClientCertificateInput.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/ClientCertificateInput.kt index 694b0421bd..9cbbd3b8c6 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/clientcertificate/ClientCertificateInput.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/ClientCertificateInput.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.clientcertificate +package app.k9mail.feature.account.server.config.ui.common import android.security.KeyChain import androidx.compose.foundation.layout.Column @@ -11,7 +11,7 @@ import androidx.compose.ui.res.stringResource import app.k9mail.core.ui.compose.common.activity.LocalActivity import app.k9mail.core.ui.compose.designsystem.atom.textfield.TextFieldOutlinedFakeSelect import app.k9mail.core.ui.compose.designsystem.molecule.input.inputContentPadding -import app.k9mail.feature.account.setup.R +import app.k9mail.feature.account.server.config.R @Composable fun ClientCertificateInput( @@ -29,7 +29,7 @@ fun ClientCertificateInput( ) { val activity = LocalActivity.current TextFieldOutlinedFakeSelect( - text = alias ?: stringResource(R.string.account_setup_client_certificate_none_selected), + text = alias ?: stringResource(R.string.account_server_config_client_certificate_none_selected), onClick = { KeyChain.choosePrivateKeyAlias(activity, onValueChange, null, null, null, -1, alias) }, diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/AuthenticationTypeStringMapper.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/AuthenticationTypeStringMapper.kt new file mode 100644 index 0000000000..59d1b221e2 --- /dev/null +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/AuthenticationTypeStringMapper.kt @@ -0,0 +1,29 @@ +package app.k9mail.feature.account.server.config.ui.common.mapper + +import android.content.res.Resources +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.server.config.R + +internal fun AuthenticationType.toResourceString(resources: Resources): String { + return when (this) { + AuthenticationType.None -> { + resources.getString(R.string.account_server_config_authentication_none) + } + + AuthenticationType.PasswordCleartext -> { + resources.getString(R.string.account_server_config_authentication_password_cleartext) + } + + AuthenticationType.PasswordEncrypted -> { + resources.getString(R.string.account_server_config_authentication_password_encrypted) + } + + AuthenticationType.ClientCertificate -> { + resources.getString(R.string.account_server_config_authentication_client_certificate) + } + + AuthenticationType.OAuth2 -> { + resources.getString(R.string.account_server_config_authentication_client_oauth) + } + } +} diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ConnectionSecurityStringMapper.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ConnectionSecurityStringMapper.kt new file mode 100644 index 0000000000..d232a961a9 --- /dev/null +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ConnectionSecurityStringMapper.kt @@ -0,0 +1,13 @@ +package app.k9mail.feature.account.server.config.ui.common.mapper + +import android.content.res.Resources +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.server.config.R + +internal fun ConnectionSecurity.toResourceString(resources: Resources): String { + return when (this) { + ConnectionSecurity.None -> resources.getString(R.string.account_server_config_connection_security_none) + ConnectionSecurity.StartTLS -> resources.getString(R.string.account_server_config_connection_security_start_tls) + ConnectionSecurity.TLS -> resources.getString(R.string.account_server_config_connection_security_ssl) + } +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupStringMapper.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ValidationErrorStringMapper.kt similarity index 52% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupStringMapper.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ValidationErrorStringMapper.kt index 3632e43d1b..949dee84da 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/AccountSetupStringMapper.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ValidationErrorStringMapper.kt @@ -1,25 +1,16 @@ -package app.k9mail.feature.account.setup.ui.common +package app.k9mail.feature.account.server.config.ui.common.mapper import android.content.res.Resources import app.k9mail.core.common.domain.usecase.validation.ValidationError -import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError -import app.k9mail.feature.account.setup.domain.usecase.ValidateImapPrefix.ValidateImapPrefixError -import app.k9mail.feature.account.setup.domain.usecase.ValidatePassword.ValidatePasswordError -import app.k9mail.feature.account.setup.domain.usecase.ValidatePort.ValidatePortError -import app.k9mail.feature.account.setup.domain.usecase.ValidateServer.ValidateServerError -import app.k9mail.feature.account.setup.domain.usecase.ValidateUsername.ValidateUsernameError +import app.k9mail.feature.account.server.config.R +import app.k9mail.feature.account.server.config.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError +import app.k9mail.feature.account.server.config.domain.usecase.ValidateImapPrefix.ValidateImapPrefixError +import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword.ValidatePasswordError +import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort.ValidatePortError +import app.k9mail.feature.account.server.config.domain.usecase.ValidateServer.ValidateServerError +import app.k9mail.feature.account.server.config.domain.usecase.ValidateUsername.ValidateUsernameError -internal fun ConnectionSecurity.toResourceString(resources: Resources): String { - return when (this) { - ConnectionSecurity.None -> resources.getString(R.string.account_setup_connection_security_none) - ConnectionSecurity.StartTLS -> resources.getString(R.string.account_setup_connection_security_start_tls) - ConnectionSecurity.TLS -> resources.getString(R.string.account_setup_connection_security_ssl) - } -} - -internal fun ValidationError.toResourceString(resources: Resources): String { +fun ValidationError.toResourceString(resources: Resources): String { return when (this) { is ValidateEmailAddressError -> toEmailAddressErrorString(resources) is ValidateServerError -> toServerErrorString(resources) @@ -34,11 +25,11 @@ internal fun ValidationError.toResourceString(resources: Resources): String { private fun ValidateEmailAddressError.toEmailAddressErrorString(resources: Resources): String { return when (this) { is ValidateEmailAddressError.EmptyEmailAddress -> resources.getString( - R.string.account_setup_validation_error_email_address_required, + R.string.account_server_config_validation_error_email_address_required, ) is ValidateEmailAddressError.InvalidEmailAddress -> resources.getString( - R.string.account_setup_validation_error_email_address_invalid, + R.string.account_server_config_validation_error_email_address_invalid, ) } } @@ -46,7 +37,7 @@ private fun ValidateEmailAddressError.toEmailAddressErrorString(resources: Resou private fun ValidateServerError.toServerErrorString(resources: Resources): String { return when (this) { is ValidateServerError.EmptyServer -> resources.getString( - R.string.account_setup_validation_error_server_required, + R.string.account_server_config_validation_error_server_required, ) } } @@ -54,11 +45,11 @@ private fun ValidateServerError.toServerErrorString(resources: Resources): Strin private fun ValidatePortError.toPortErrorString(resources: Resources): String { return when (this) { is ValidatePortError.EmptyPort -> resources.getString( - R.string.account_setup_validation_error_port_required, + R.string.account_server_config_validation_error_port_required, ) is ValidatePortError.InvalidPort -> resources.getString( - R.string.account_setup_validation_error_port_invalid, + R.string.account_server_config_validation_error_port_invalid, ) } } @@ -66,7 +57,7 @@ private fun ValidatePortError.toPortErrorString(resources: Resources): String { private fun ValidateUsernameError.toUsernameErrorString(resources: Resources): String { return when (this) { ValidateUsernameError.EmptyUsername -> resources.getString( - R.string.account_setup_validation_error_username_required, + R.string.account_server_config_validation_error_username_required, ) } } @@ -74,7 +65,7 @@ private fun ValidateUsernameError.toUsernameErrorString(resources: Resources): S private fun ValidatePasswordError.toPasswordErrorString(resources: Resources): String { return when (this) { ValidatePasswordError.EmptyPassword -> resources.getString( - R.string.account_setup_validation_error_password_required, + R.string.account_server_config_validation_error_password_required, ) } } @@ -82,7 +73,7 @@ private fun ValidatePasswordError.toPasswordErrorString(resources: Resources): S private fun ValidateImapPrefixError.toImapPrefixErrorString(resources: Resources): String { return when (this) { ValidateImapPrefixError.BlankImapPrefix -> resources.getString( - R.string.account_setup_validation_error_imap_prefix_blank, + R.string.account_server_config_validation_error_imap_prefix_blank, ) } } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContent.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContent.kt similarity index 89% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContent.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContent.kt index 2cd1a405cf..83aec7853d 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContent.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContent.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues @@ -28,12 +28,11 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.ui.item.defaultItemPadding -import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.ui.clientcertificate.ClientCertificateInput -import app.k9mail.feature.account.setup.ui.common.mapper.toResourceString -import app.k9mail.feature.account.setup.ui.common.toResourceString -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.config.R +import app.k9mail.feature.account.server.config.ui.common.ClientCertificateInput +import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State @Suppress("LongMethod") @Composable @@ -68,7 +67,7 @@ internal fun AccountIncomingConfigContent( options = IncomingProtocolType.all(), selectedOption = state.protocolType, onOptionChange = { onEvent(Event.ProtocolTypeChanged(it)) }, - label = stringResource(id = R.string.account_setup_incoming_config_protocol_type_label), + label = stringResource(id = R.string.account_server_config_protocol_type_label), contentPadding = defaultItemPadding(), ) } @@ -78,7 +77,7 @@ internal fun AccountIncomingConfigContent( text = state.server.value, errorMessage = state.server.error?.toResourceString(resources), onTextChange = { onEvent(Event.ServerChanged(it)) }, - label = stringResource(id = R.string.account_setup_incoming_config_server_label), + label = stringResource(id = R.string.account_server_config_server_label), contentPadding = defaultItemPadding(), ) } @@ -89,7 +88,7 @@ internal fun AccountIncomingConfigContent( optionToStringTransformation = { it.toResourceString(resources) }, selectedOption = state.security, onOptionChange = { onEvent(Event.SecurityChanged(it)) }, - label = stringResource(id = R.string.account_setup_incoming_config_security_label), + label = stringResource(id = R.string.account_server_config_security_label), contentPadding = defaultItemPadding(), ) } @@ -99,7 +98,7 @@ internal fun AccountIncomingConfigContent( value = state.port.value, errorMessage = state.port.error?.toResourceString(resources), onValueChange = { onEvent(Event.PortChanged(it)) }, - label = stringResource(id = R.string.account_setup_outgoing_config_port_label), + label = stringResource(id = R.string.account_server_config_port_label), contentPadding = defaultItemPadding(), ) } @@ -110,7 +109,7 @@ internal fun AccountIncomingConfigContent( optionToStringTransformation = { it.toResourceString(resources) }, selectedOption = state.authenticationType, onOptionChange = { onEvent(Event.AuthenticationTypeChanged(it)) }, - label = stringResource(id = R.string.account_setup_incoming_config_authentication_label), + label = stringResource(id = R.string.account_server_config_authentication_label), contentPadding = defaultItemPadding(), ) } @@ -120,7 +119,7 @@ internal fun AccountIncomingConfigContent( text = state.username.value, errorMessage = state.username.error?.toResourceString(resources), onTextChange = { onEvent(Event.UsernameChanged(it)) }, - label = stringResource(id = R.string.account_setup_outgoing_config_username_label), + label = stringResource(id = R.string.account_server_config_username_label), contentPadding = defaultItemPadding(), ) } @@ -140,7 +139,7 @@ internal fun AccountIncomingConfigContent( ClientCertificateInput( alias = state.clientCertificateAlias, onValueChange = { onEvent(Event.ClientCertificateChanged(it)) }, - label = stringResource(id = R.string.account_setup_client_certificate_label), + label = stringResource(id = R.string.account_server_config_client_certificate_label), contentPadding = defaultItemPadding(), ) } @@ -148,7 +147,7 @@ internal fun AccountIncomingConfigContent( if (state.protocolType == IncomingProtocolType.IMAP) { item { CheckboxInput( - text = stringResource(id = R.string.account_setup_incoming_config_imap_namespace_label), + text = stringResource(id = R.string.account_server_config_incoming_imap_namespace_label), checked = state.imapAutodetectNamespaceEnabled, onCheckedChange = { onEvent(Event.ImapAutoDetectNamespaceChanged(it)) }, contentPadding = defaultItemPadding(), @@ -159,7 +158,7 @@ internal fun AccountIncomingConfigContent( if (state.imapAutodetectNamespaceEnabled) { TextInput( onTextChange = {}, - label = stringResource(id = R.string.account_setup_incoming_config_imap_prefix_label), + label = stringResource(id = R.string.account_server_config_incoming_imap_prefix_label), contentPadding = defaultItemPadding(), isEnabled = false, ) @@ -168,7 +167,7 @@ internal fun AccountIncomingConfigContent( text = state.imapPrefix.value, errorMessage = state.imapPrefix.error?.toResourceString(resources), onTextChange = { onEvent(Event.ImapPrefixChanged(it)) }, - label = stringResource(id = R.string.account_setup_incoming_config_imap_prefix_label), + label = stringResource(id = R.string.account_server_config_incoming_imap_prefix_label), contentPadding = defaultItemPadding(), ) } @@ -176,7 +175,7 @@ internal fun AccountIncomingConfigContent( item { CheckboxInput( - text = stringResource(id = R.string.account_setup_incoming_config_imap_compression_label), + text = stringResource(id = R.string.account_server_config_incoming_imap_compression_label), checked = state.imapUseCompression, onCheckedChange = { onEvent(Event.ImapUseCompressionChanged(it)) }, contentPadding = defaultItemPadding(), @@ -185,7 +184,7 @@ internal fun AccountIncomingConfigContent( item { CheckboxInput( - text = stringResource(R.string.account_setup_incoming_config_imap_send_client_id_label), + text = stringResource(R.string.account_server_config_incoming_imap_send_client_id_label), checked = state.imapSendClientId, onCheckedChange = { onEvent(Event.ImapSendClientIdChanged(it)) }, contentPadding = defaultItemPadding(), diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContract.kt similarity index 98% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContract.kt index 4be0fdc556..e361477ff1 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigContract.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContract.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreen.kt similarity index 82% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreen.kt index aba49a064f..56dc8a36c9 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreen.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreen.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import androidx.activity.compose.BackHandler import androidx.compose.runtime.Composable @@ -13,13 +13,13 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.ui.AccountTopAppBar import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository -import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.ViewModel +import app.k9mail.feature.account.server.config.R +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.ViewModel @Composable -internal fun AccountIncomingConfigScreen( +fun AccountIncomingConfigScreen( onNext: (AccountIncomingConfigContract.State) -> Unit, onBack: () -> Unit, viewModel: ViewModel, @@ -43,7 +43,7 @@ internal fun AccountIncomingConfigScreen( Scaffold( topBar = { AccountTopAppBar( - title = stringResource(id = R.string.account_setup_incoming_config_top_bar_title), + title = stringResource(id = R.string.account_server_config_incoming_top_bar_title), ) }, bottomBar = { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateExtensions.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateExtensions.kt similarity index 95% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateExtensions.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateExtensions.kt index d586bcc803..5826868e40 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateExtensions.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateExtensions.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapper.kt similarity index 94% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapper.kt index 95f5f5fdac..ed0e1bb96f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapper.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapper.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType @@ -8,7 +8,7 @@ import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.store.imap.ImapStoreSettings diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigValidator.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigValidator.kt similarity index 68% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigValidator.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigValidator.kt index 662e605db2..4789900475 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigValidator.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigValidator.kt @@ -1,12 +1,12 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.setup.domain.DomainContract.UseCase -import app.k9mail.feature.account.setup.domain.usecase.ValidateImapPrefix -import app.k9mail.feature.account.setup.domain.usecase.ValidatePassword -import app.k9mail.feature.account.setup.domain.usecase.ValidatePort -import app.k9mail.feature.account.setup.domain.usecase.ValidateServer -import app.k9mail.feature.account.setup.domain.usecase.ValidateUsername +import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.config.domain.usecase.ValidateImapPrefix +import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword +import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort +import app.k9mail.feature.account.server.config.domain.usecase.ValidateServer +import app.k9mail.feature.account.server.config.domain.usecase.ValidateUsername internal class AccountIncomingConfigValidator( private val serverValidator: UseCase.ValidateServer = ValidateServer(), diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModel.kt similarity index 89% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModel.kt index 647faf3512..4ea05db564 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModel.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModel.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel @@ -6,13 +6,13 @@ import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.toDefaultPort -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Validator -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.ViewModel +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Validator +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.ViewModel -internal class AccountIncomingConfigViewModel( +class AccountIncomingConfigViewModel( private val validator: Validator, private val accountStateRepository: AccountDomainContract.AccountStateRepository, initialState: State? = null, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/FakeAccountIncomingConfigValidator.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt similarity index 86% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/FakeAccountIncomingConfigValidator.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt index 9835314489..e9d21564fe 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/FakeAccountIncomingConfigValidator.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt @@ -1,6 +1,7 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming.fake import app.k9mail.core.common.domain.usecase.validation.ValidationResult +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract class FakeAccountIncomingConfigValidator( private val serverAnswer: ValidationResult = ValidationResult.Success, diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt new file mode 100644 index 0000000000..6613f9abdd --- /dev/null +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt @@ -0,0 +1,22 @@ +package app.k9mail.feature.account.server.config.ui.incoming.fake + +import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.ViewModel + +class FakeAccountIncomingConfigViewModel( + initialState: State = State(), +) : BaseViewModel(initialState), ViewModel { + + val events = mutableListOf() + + override fun event(event: Event) { + events.add(event) + } + + fun effect(effect: Effect) { + emitEffect(effect) + } +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContent.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContent.kt similarity index 89% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContent.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContent.kt index 1debb3fe3d..71b9236786 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContent.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContent.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues @@ -27,12 +27,11 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.ui.item.defaultItemPadding -import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.ui.clientcertificate.ClientCertificateInput -import app.k9mail.feature.account.setup.ui.common.mapper.toResourceString -import app.k9mail.feature.account.setup.ui.common.toResourceString -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.config.R +import app.k9mail.feature.account.server.config.ui.common.ClientCertificateInput +import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State @Suppress("LongMethod") @Composable @@ -67,7 +66,7 @@ internal fun AccountOutgoingConfigContent( text = state.server.value, errorMessage = state.server.error?.toResourceString(resources), onTextChange = { onEvent(Event.ServerChanged(it)) }, - label = stringResource(id = R.string.account_setup_outgoing_config_server_label), + label = stringResource(id = R.string.account_server_config_server_label), isRequired = true, contentPadding = defaultItemPadding(), ) @@ -79,7 +78,7 @@ internal fun AccountOutgoingConfigContent( optionToStringTransformation = { it.toResourceString(resources) }, selectedOption = state.security, onOptionChange = { onEvent(Event.SecurityChanged(it)) }, - label = stringResource(id = R.string.account_setup_outgoing_config_security_label), + label = stringResource(id = R.string.account_server_config_security_label), contentPadding = defaultItemPadding(), ) } @@ -89,7 +88,7 @@ internal fun AccountOutgoingConfigContent( value = state.port.value, errorMessage = state.port.error?.toResourceString(resources), onValueChange = { onEvent(Event.PortChanged(it)) }, - label = stringResource(id = R.string.account_setup_outgoing_config_port_label), + label = stringResource(id = R.string.account_server_config_port_label), isRequired = true, contentPadding = defaultItemPadding(), ) @@ -101,7 +100,7 @@ internal fun AccountOutgoingConfigContent( optionToStringTransformation = { it.toResourceString(resources) }, selectedOption = state.authenticationType, onOptionChange = { onEvent(Event.AuthenticationTypeChanged(it)) }, - label = stringResource(id = R.string.account_setup_outgoing_config_authentication_label), + label = stringResource(id = R.string.account_server_config_authentication_label), contentPadding = defaultItemPadding(), ) } @@ -112,7 +111,7 @@ internal fun AccountOutgoingConfigContent( text = state.username.value, errorMessage = state.username.error?.toResourceString(resources), onTextChange = { onEvent(Event.UsernameChanged(it)) }, - label = stringResource(id = R.string.account_setup_outgoing_config_username_label), + label = stringResource(id = R.string.account_server_config_username_label), isRequired = true, contentPadding = defaultItemPadding(), ) @@ -135,7 +134,7 @@ internal fun AccountOutgoingConfigContent( ClientCertificateInput( alias = state.clientCertificateAlias, onValueChange = { onEvent(Event.ClientCertificateChanged(it)) }, - label = stringResource(id = R.string.account_setup_client_certificate_label), + label = stringResource(id = R.string.account_server_config_client_certificate_label), contentPadding = defaultItemPadding(), ) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContract.kt similarity index 97% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContract.kt index 29b50f318e..51cc1dd878 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigContract.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContract.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreen.kt similarity index 82% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreen.kt index e1c184633c..82a50f1504 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreen.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreen.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing import androidx.activity.compose.BackHandler import androidx.compose.runtime.Composable @@ -13,13 +13,13 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.ui.AccountTopAppBar import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository -import app.k9mail.feature.account.setup.R -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.ViewModel +import app.k9mail.feature.account.server.config.R +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.ViewModel @Composable -internal fun AccountOutgoingConfigScreen( +fun AccountOutgoingConfigScreen( onNext: () -> Unit, onBack: () -> Unit, viewModel: ViewModel, @@ -43,7 +43,7 @@ internal fun AccountOutgoingConfigScreen( Scaffold( topBar = { AccountTopAppBar( - title = stringResource(id = R.string.account_setup_outgoing_config_top_bar_title), + title = stringResource(id = R.string.account_server_config_outgoing_top_bar_title), ) }, bottomBar = { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateExtensions.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateExtensions.kt similarity index 81% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateExtensions.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateExtensions.kt index d80ffca578..a5b4544b00 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateExtensions.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateExtensions.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing internal val AccountOutgoingConfigContract.State.isUsernameFieldVisible: Boolean get() = authenticationType.isUsernameRequired diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapper.kt similarity index 92% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapper.kt index 1a4ac97455..5ff993d0d3 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapper.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapper.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.entity.toAuthType @@ -7,7 +7,7 @@ import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State import com.fsck.k9.mail.ServerSettings internal fun AccountState.toOutgoingConfigState(): State { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigValidator.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigValidator.kt similarity index 71% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigValidator.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigValidator.kt index a4c71d35e4..db073d78f6 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigValidator.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigValidator.kt @@ -1,10 +1,10 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.setup.domain.usecase.ValidatePassword -import app.k9mail.feature.account.setup.domain.usecase.ValidatePort -import app.k9mail.feature.account.setup.domain.usecase.ValidateServer -import app.k9mail.feature.account.setup.domain.usecase.ValidateUsername +import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword +import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort +import app.k9mail.feature.account.server.config.domain.usecase.ValidateServer +import app.k9mail.feature.account.server.config.domain.usecase.ValidateUsername internal class AccountOutgoingConfigValidator( private val serverValidator: ValidateServer = ValidateServer(), diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModel.kt similarity index 85% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModel.kt index a01369ec5e..b706474c01 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModel.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModel.kt @@ -1,17 +1,17 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Validator -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.ViewModel +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Validator +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.ViewModel -internal class AccountOutgoingConfigViewModel( +class AccountOutgoingConfigViewModel( private val validator: Validator, private val accountStateRepository: AccountDomainContract.AccountStateRepository, initialState: State? = State(), diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/FakeAccountOutgoingConfigValidator.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt similarity index 83% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/FakeAccountOutgoingConfigValidator.kt rename to feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt index 5c342e9959..4589ad7147 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/FakeAccountOutgoingConfigValidator.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt @@ -1,6 +1,7 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing.fake import app.k9mail.core.common.domain.usecase.validation.ValidationResult +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract class FakeAccountOutgoingConfigValidator( private val serverAnswer: ValidationResult = ValidationResult.Success, diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt new file mode 100644 index 0000000000..5830438542 --- /dev/null +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt @@ -0,0 +1,22 @@ +package app.k9mail.feature.account.server.config.ui.outgoing.fake + +import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.ViewModel + +class FakeAccountOutgoingConfigViewModel( + initialState: State = State(), +) : BaseViewModel(initialState), ViewModel { + + val events = mutableListOf() + + override fun event(event: Event) { + events.add(event) + } + + fun effect(effect: Effect) { + emitEffect(effect) + } +} diff --git a/feature/account/server/config/src/main/res/values/strings.xml b/feature/account/server/config/src/main/res/values/strings.xml new file mode 100644 index 0000000000..a32a430c65 --- /dev/null +++ b/feature/account/server/config/src/main/res/values/strings.xml @@ -0,0 +1,40 @@ + + + Protocol + Server + Security + Port + Authentication + Username + + None + StartTLS + SSL/TLS + + None + Normal password + Encrypted password + Client certificate + OAuth 2.0 + + None + Client certificate + + Incoming server settings + + Auto-detect IMAP namespace + IMAP path prefix + Use compression + Send client ID + + Outgoing server settings + + Email address is required. + Email address is invalid. + Server name is required. + Port is required. + Port is invalid (must be 1–65535). + Username is required. + Password is required. + Imap prefix can\'t be blank. + diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddressTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddressTest.kt similarity index 86% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddressTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddressTest.kt index c00d35ed70..2549d11d11 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddressTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddressTest.kt @@ -1,7 +1,7 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.setup.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError +import app.k9mail.feature.account.server.config.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError import assertk.assertThat import assertk.assertions.isInstanceOf import assertk.assertions.prop diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateImapPrefixTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefixTest.kt similarity index 93% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateImapPrefixTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefixTest.kt index 02cef9f345..7b209f526b 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateImapPrefixTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefixTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult import assertk.assertThat diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePasswordTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePasswordTest.kt similarity index 94% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePasswordTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePasswordTest.kt index 5f6b85e10d..18f5fb6a26 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePasswordTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePasswordTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult import assertk.assertThat diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePortTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePortTest.kt similarity index 91% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePortTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePortTest.kt index ea3600dcfa..450667556d 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidatePortTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePortTest.kt @@ -1,7 +1,7 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.setup.domain.usecase.ValidatePort.ValidatePortError +import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort.ValidatePortError import assertk.assertThat import assertk.assertions.isInstanceOf import assertk.assertions.prop diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServerTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServerTest.kt similarity index 94% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServerTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServerTest.kt index c0278d4892..ac51fc7d55 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateServerTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServerTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult import assertk.assertThat diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateUsernameTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsernameTest.kt similarity index 94% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateUsernameTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsernameTest.kt index d9a26c4678..4ac73fda0f 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateUsernameTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsernameTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.domain.usecase +package app.k9mail.feature.account.server.config.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult import assertk.assertThat diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreenKtTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreenKtTest.kt similarity index 76% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreenKtTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreenKtTest.kt index 4525f25348..ac708f544b 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigScreenKtTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreenKtTest.kt @@ -1,9 +1,10 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.setContent -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.config.ui.incoming.fake.FakeAccountIncomingConfigViewModel import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt similarity index 95% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt index f56740d48f..5d146b07d9 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity @@ -6,7 +6,7 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateTest.kt similarity index 89% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateTest.kt index 6a05191532..93d4460451 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigStateTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity @@ -6,7 +6,7 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModelTest.kt similarity index 97% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModelTest.kt index d470f1284a..74ec973172 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/AccountIncomingConfigViewModelTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModelTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.incoming +package app.k9mail.feature.account.server.config.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult @@ -18,9 +18,10 @@ import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort import app.k9mail.feature.account.common.domain.entity.toPop3DefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.config.ui.incoming.fake.FakeAccountIncomingConfigValidator import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt similarity index 76% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt index 0de96e850d..b2bf06990c 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt @@ -1,9 +1,10 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.setContent -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.config.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt similarity index 90% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt index a6394e6f86..f16773c9d9 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt @@ -1,11 +1,11 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateTest.kt similarity index 87% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateTest.kt index 0ae7ac7faf..6205639bfa 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigStateTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateTest.kt @@ -1,11 +1,11 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModelTest.kt similarity index 96% rename from feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt rename to feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModelTest.kt index 31c3f8fc45..4a38c3c311 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/AccountOutgoingConfigViewModelTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModelTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.setup.ui.outgoing +package app.k9mail.feature.account.server.config.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult @@ -16,9 +16,10 @@ import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.config.ui.outgoing.fake.FakeAccountOutgoingConfigValidator import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType diff --git a/feature/account/setup/build.gradle.kts b/feature/account/setup/build.gradle.kts index 697507561c..659472c308 100644 --- a/feature/account/setup/build.gradle.kts +++ b/feature/account/setup/build.gradle.kts @@ -29,6 +29,7 @@ dependencies { api(projects.feature.account.common) implementation(projects.feature.account.oauth) + implementation(projects.feature.account.server.config) implementation(projects.feature.account.server.certificate) api(projects.feature.account.server.validation) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt index 7dfbce6991..6a2aee0c07 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt @@ -4,6 +4,7 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryService import app.k9mail.autodiscovery.service.RealAutoDiscoveryService import app.k9mail.feature.account.common.featureAccountCommonModule import app.k9mail.feature.account.oauth.featureAccountOAuthModule +import app.k9mail.feature.account.server.config.featureAccountServerConfigModule import app.k9mail.feature.account.server.validation.featureAccountServerValidationModule import app.k9mail.feature.account.setup.domain.DomainContract import app.k9mail.feature.account.setup.domain.usecase.CreateAccount @@ -12,15 +13,9 @@ import app.k9mail.feature.account.setup.ui.AccountSetupViewModel import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryValidator import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryViewModel -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigValidator -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigViewModel import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsValidator import app.k9mail.feature.account.setup.ui.options.AccountOptionsViewModel -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigValidator -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigViewModel import okhttp3.OkHttpClient import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.core.module.Module @@ -31,6 +26,7 @@ val featureAccountSetupModule: Module = module { featureAccountCommonModule, featureAccountOAuthModule, featureAccountServerValidationModule, + featureAccountServerConfigModule, ) single { @@ -57,8 +53,6 @@ val featureAccountSetupModule: Module = module { } factory { AccountAutoDiscoveryValidator() } - factory { AccountIncomingConfigValidator() } - factory { AccountOutgoingConfigValidator() } factory { AccountOptionsValidator() } viewModel { @@ -75,19 +69,6 @@ val featureAccountSetupModule: Module = module { oAuthViewModel = get(), ) } - viewModel { - AccountIncomingConfigViewModel( - validator = get(), - accountStateRepository = get(), - ) - } - - viewModel { - AccountOutgoingConfigViewModel( - validator = get(), - accountStateRepository = get(), - ) - } viewModel { AccountOptionsViewModel( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt index f7d06c3bce..1e49c57d79 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt @@ -4,7 +4,6 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryResult import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.feature.account.common.domain.entity.AccountOptions import com.fsck.k9.mail.ServerSettings -import java.security.cert.X509Certificate interface DomainContract { @@ -13,10 +12,6 @@ interface DomainContract { suspend fun execute(emailAddress: String): AutoDiscoveryResult } - fun interface AddServerCertificateException { - suspend fun addCertificate(hostname: String, port: Int, certificate: X509Certificate?) - } - fun interface CreateAccount { suspend fun execute( emailAddress: String, @@ -27,34 +22,10 @@ interface DomainContract { ): String } - fun interface ValidateEmailAddress { - fun execute(emailAddress: String): ValidationResult - } - - fun interface ValidatePassword { - fun execute(password: String): ValidationResult - } - fun interface ValidateConfigurationApproval { fun execute(isApproved: Boolean?, isAutoDiscoveryTrusted: Boolean?): ValidationResult } - fun interface ValidateServer { - fun execute(server: String): ValidationResult - } - - fun interface ValidatePort { - fun execute(port: Long?): ValidationResult - } - - fun interface ValidateUsername { - fun execute(username: String): ValidationResult - } - - fun interface ValidateImapPrefix { - fun execute(imapPrefix: String): ValidationResult - } - fun interface ValidateAccountName { fun execute(accountName: String): ValidationResult } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt index b9dd2513d0..d2f9cc155e 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt @@ -3,6 +3,12 @@ package app.k9mail.feature.account.setup.ui import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview import app.k9mail.core.ui.compose.common.mvi.observe +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigScreen +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigViewModel +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigScreen +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigViewModel import app.k9mail.feature.account.server.validation.KOIN_NAME_INCOMING_SERVER_VALIDATION import app.k9mail.feature.account.server.validation.KOIN_NAME_OUTGOING_SERVER_VALIDATION import app.k9mail.feature.account.server.validation.ui.ServerValidationContract @@ -15,15 +21,9 @@ import app.k9mail.feature.account.setup.ui.AccountSetupContract.ViewModel import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryScreen import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryViewModel -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigScreen -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigViewModel import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsScreen import app.k9mail.feature.account.setup.ui.options.AccountOptionsViewModel -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigScreen -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigViewModel import org.koin.androidx.compose.koinViewModel import org.koin.core.qualifier.named diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt index a0dd9b217e..0b515289f3 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt @@ -53,13 +53,13 @@ internal fun AccountAutoDiscoveryContent( if (state.isLoading) { item(key = "loading") { LoadingItem( - message = stringResource(id = R.string.account_setup_auto_config_loading_message), + message = stringResource(id = R.string.account_setup_auto_discovery_loading_message), ) } } else if (state.error != null) { item(key = "error") { ErrorItem( - title = stringResource(id = R.string.account_setup_auto_config_loading_error), + title = stringResource(id = R.string.account_setup_auto_discovery_loading_error), message = state.error.toResourceString(resources), onRetry = { onEvent(Event.OnRetryClicked) }, ) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt index 5cea5b8cd0..76f1599846 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt @@ -5,13 +5,13 @@ import app.k9mail.autodiscovery.api.SmtpServerSettings import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toIncomingProtocolType import app.k9mail.feature.account.setup.domain.toServerSettings -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract internal fun AccountAutoDiscoveryContract.State.toAccountState(): AccountState { return AccountState( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt index 2ae80059e5..a6b8ca3e6d 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt @@ -1,14 +1,15 @@ package app.k9mail.feature.account.setup.ui.autodiscovery import app.k9mail.core.common.domain.usecase.validation.ValidationResult +import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract +import app.k9mail.feature.account.server.config.domain.usecase.ValidateEmailAddress +import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword import app.k9mail.feature.account.setup.domain.DomainContract.UseCase import app.k9mail.feature.account.setup.domain.usecase.ValidateConfigurationApproval -import app.k9mail.feature.account.setup.domain.usecase.ValidateEmailAddress -import app.k9mail.feature.account.setup.domain.usecase.ValidatePassword internal class AccountAutoDiscoveryValidator( - private val emailAddressValidator: UseCase.ValidateEmailAddress = ValidateEmailAddress(), - private val passwordValidator: UseCase.ValidatePassword = ValidatePassword(), + private val emailAddressValidator: ServerConfigDomainContract.UseCase.ValidateEmailAddress = ValidateEmailAddress(), + private val passwordValidator: ServerConfigDomainContract.UseCase.ValidatePassword = ValidatePassword(), private val configurationApprovalValidator: UseCase.ValidateConfigurationApproval = ValidateConfigurationApproval(), ) : AccountAutoDiscoveryContract.Validator { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt index 19d8749ce7..33823b6c4d 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt @@ -9,11 +9,11 @@ import app.k9mail.feature.account.setup.domain.usecase.ValidateConfigurationAppr internal fun AutoDiscoveryConnectionSecurity.toResourceString(resources: Resources): String { return when (this) { AutoDiscoveryConnectionSecurity.StartTLS -> resources.getString( - R.string.account_setup_connection_security_start_tls, + R.string.account_setup_auto_discovery_connection_security_start_tls, ) AutoDiscoveryConnectionSecurity.TLS -> resources.getString( - R.string.account_setup_connection_security_ssl, + R.string.account_setup_auto_discovery_connection_security_ssl, ) } } @@ -40,7 +40,7 @@ private fun ValidateConfigurationApproval.ValidateConfigurationApprovalError.toC ): String { return when (this) { ValidateConfigurationApproval.ValidateConfigurationApprovalError.ApprovalRequired -> resources.getString( - R.string.account_setup_error_configuration_approval_required, + R.string.account_setup_auto_discovery_error_configuration_approval_required, ) } } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/EmailAddressItem.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/EmailAddressItem.kt index 6e4d13b586..de73de1061 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/EmailAddressItem.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/EmailAddressItem.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.platform.LocalContext import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.ui.compose.designsystem.molecule.input.EmailAddressInput import app.k9mail.feature.account.common.ui.item.ListItem -import app.k9mail.feature.account.setup.ui.common.toResourceString +import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString @Composable internal fun LazyItemScope.EmailAddressItem( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/PasswordItem.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/PasswordItem.kt index a606f9d483..6e613e2f33 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/PasswordItem.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/PasswordItem.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.platform.LocalContext import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.ui.compose.designsystem.molecule.input.PasswordInput import app.k9mail.feature.account.common.ui.item.ListItem -import app.k9mail.feature.account.setup.ui.common.toResourceString +import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString @Composable internal fun LazyItemScope.PasswordItem( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryServerSettingsView.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryServerSettingsView.kt index d20b0748fb..9a86dc34d1 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryServerSettingsView.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryServerSettingsView.kt @@ -27,7 +27,6 @@ import app.k9mail.core.ui.compose.theme.Icons import app.k9mail.core.ui.compose.theme.MainTheme import app.k9mail.core.ui.compose.theme.PreviewWithThemes import app.k9mail.feature.account.setup.ui.autodiscovery.toResourceString -import app.k9mail.feature.account.setup.ui.common.toResourceString @Composable internal fun AutoDiscoveryServerSettingsView( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusBodyView.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusBodyView.kt index a037618f5e..9f9377ee28 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusBodyView.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusBodyView.kt @@ -42,7 +42,7 @@ internal fun AutoDiscoveryStatusBodyView( Spacer(modifier = Modifier.height(MainTheme.sizes.smaller)) TextBody2( text = stringResource( - id = R.string.account_setup_auto_config_status_disclaimer_untrusted_configuration, + id = R.string.account_setup_auto_discovery_status_disclaimer_untrusted_configuration, ), modifier = Modifier.fillMaxWidth(), ) @@ -94,7 +94,7 @@ internal fun EditConfigurationButton( .then(modifier), ) { ButtonText( - text = stringResource(id = R.string.account_setup_auto_config_status_edit_configuration_button_label), + text = stringResource(id = R.string.account_setup_auto_discovery_status_edit_configuration_button_label), onClick = onEditConfigurationClick, color = MainTheme.colors.warning, contentPadding = buttonContentPadding( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusHeaderState.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusHeaderState.kt index de36f44fcc..54a727234e 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusHeaderState.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusHeaderState.kt @@ -13,22 +13,22 @@ enum class AutoDiscoveryStatusHeaderState( ) { NoSettings( icon = Icons.Outlined.info, - titleResourceId = R.string.account_setup_auto_config_status_header_title_configuration_not_found, - subtitleResourceId = R.string.account_setup_auto_config_status_header_subtitle_configuration_not_found, + titleResourceId = R.string.account_setup_auto_discovery_status_header_title_configuration_not_found, + subtitleResourceId = R.string.account_setup_auto_discovery_status_header_subtitle_configuration_not_found, isExpandable = false, ), Trusted( icon = Icons.Outlined.check, - titleResourceId = R.string.account_setup_auto_config_status_header_title_configuration_found, - subtitleResourceId = R.string.account_setup_auto_config_status_header_subtitle_configuration_trusted, + titleResourceId = R.string.account_setup_auto_discovery_status_header_title_configuration_found, + subtitleResourceId = R.string.account_setup_auto_discovery_status_header_subtitle_configuration_trusted, isExpandable = true, ), Untrusted( icon = Icons.Outlined.info, - titleResourceId = R.string.account_setup_auto_config_status_header_title_configuration_found, - subtitleResourceId = R.string.account_setup_auto_config_status_header_subtitle_configuration_untrusted, + titleResourceId = R.string.account_setup_auto_discovery_status_header_title_configuration_found, + subtitleResourceId = R.string.account_setup_auto_discovery_status_header_subtitle_configuration_untrusted, isExpandable = true, ), } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt index 26e0ad170a..1857ea4c42 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt @@ -24,7 +24,7 @@ internal fun ConfigurationApprovalView( CheckboxInput( text = stringResource( - id = R.string.account_setup_auto_config_status_checkbox_configuration_untrusted_confirmation_label, + id = R.string.account_setup_auto_discovery_status_checkbox_configuration_untrusted_confirmation_label, ), checked = approvalState.value ?: false, onCheckedChange = onConfigurationApprovalChange, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/mapper/AuthenticationTypeStringMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/mapper/AuthenticationTypeStringMapper.kt deleted file mode 100644 index 5ec5ebebee..0000000000 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/common/mapper/AuthenticationTypeStringMapper.kt +++ /dev/null @@ -1,25 +0,0 @@ -package app.k9mail.feature.account.setup.ui.common.mapper - -import android.content.res.Resources -import app.k9mail.feature.account.common.domain.entity.AuthenticationType -import app.k9mail.feature.account.setup.R - -internal fun AuthenticationType.toResourceString(resources: Resources): String { - return when (this) { - AuthenticationType.None -> { - resources.getString(R.string.account_setup_authentication_none) - } - AuthenticationType.PasswordCleartext -> { - resources.getString(R.string.account_setup_authentication_password_cleartext) - } - AuthenticationType.PasswordEncrypted -> { - resources.getString(R.string.account_setup_authentication_password_encrypted) - } - AuthenticationType.ClientCertificate -> { - resources.getString(R.string.account_setup_authentication_client_certificate) - } - AuthenticationType.OAuth2 -> { - resources.getString(R.string.account_setup_authentication_client_oauth) - } - } -} diff --git a/feature/account/setup/src/main/res/values/strings.xml b/feature/account/setup/src/main/res/values/strings.xml index 19e84d79c8..21cc780041 100644 --- a/feature/account/setup/src/main/res/values/strings.xml +++ b/feature/account/setup/src/main/res/values/strings.xml @@ -2,57 +2,23 @@ K-9 Mail Finish - None - SSL/TLS - StartTLS - None - Normal password - Encrypted password - Client certificate - OAuth 2.0 - Client certificate - None Network Unknown error - Email address is required. - Email address is invalid. - Server name is required. - Port is required. - Port is invalid (must be 1–65535). - Username is required. - Password is required. - Imap prefix can\'t be blank. - - Finding email details - Failed to load email configuration - Configuration Found - Configuration Not Found - Configure automatically - This configuration is not trusted - We received the configuration for your email server over a connection that isn\'t as secure as we\'d like. This means that there is a tiny chance that someone could have altered it. Could you please double-check the provided configuration to make sure it\'s as it should be? - Configure manually - Edit configuration - I trust this configuration - It is required to approve the configuration. - - Incoming server settings - Protocol - Server - Security - Authentication - Auto-detect IMAP namespace - IMAP path prefix - Use compression - Send client ID - - Outgoing server settings - Server - Security - Port - Authentication - Username + StartTLS + SSL/TLS + Finding email details + Failed to load email configuration + Configuration Found + Configuration Not Found + Configure automatically + This configuration is not trusted + We received the configuration for your email server over a connection that isn\'t as secure as we\'d like. This means that there is a tiny chance that someone could have altered it. Could you please double-check the provided configuration to make sure it\'s as it should be? + Configure manually + Edit configuration + I trust this configuration + It is required to approve the configuration. Account options Display options diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index da60b42513..c568c561fc 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -5,14 +5,14 @@ import app.k9mail.core.common.oauth.OAuthConfigurationFactory import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.server.validation.ui.ServerValidationContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult import app.k9mail.feature.account.setup.ui.AccountSetupContract import app.k9mail.feature.account.setup.ui.autodiscovery.AccountAutoDiscoveryContract -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract import com.fsck.k9.mail.oauth.AuthStateStorage import com.fsck.k9.mail.oauth.OAuth2TokenProvider import com.fsck.k9.mail.oauth.OAuth2TokenProviderFactory diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt index 2226f350db..0c1ddb272a 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt @@ -4,14 +4,14 @@ import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.onNodeWithTag import app.k9mail.core.ui.compose.testing.setContent import app.k9mail.core.ui.compose.theme.ThunderbirdTheme +import app.k9mail.feature.account.server.config.ui.incoming.fake.FakeAccountIncomingConfigViewModel +import app.k9mail.feature.account.server.config.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel import app.k9mail.feature.account.server.validation.ui.fake.FakeServerValidationViewModel import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep import app.k9mail.feature.account.setup.ui.AccountSetupContract.State import app.k9mail.feature.account.setup.ui.autodiscovery.FakeAccountAutoDiscoveryViewModel -import app.k9mail.feature.account.setup.ui.incoming.FakeAccountIncomingConfigViewModel import app.k9mail.feature.account.setup.ui.options.FakeAccountOptionsViewModel -import app.k9mail.feature.account.setup.ui.outgoing.FakeAccountOutgoingConfigViewModel import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt index 0f144be8a6..4e668b7366 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt @@ -10,12 +10,12 @@ import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField +import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/FakeAccountIncomingConfigViewModel.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/FakeAccountIncomingConfigViewModel.kt deleted file mode 100644 index 3fda4d2e77..0000000000 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/incoming/FakeAccountIncomingConfigViewModel.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.k9mail.feature.account.setup.ui.incoming - -import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.setup.ui.incoming.AccountIncomingConfigContract.ViewModel - -class FakeAccountIncomingConfigViewModel( - initialState: State = State(), -) : BaseViewModel(initialState), ViewModel { - - val events = mutableListOf() - - override fun event(event: Event) { - events.add(event) - } - - fun effect(effect: Effect) { - emitEffect(effect) - } -} diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/FakeAccountOutgoingConfigViewModel.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/FakeAccountOutgoingConfigViewModel.kt deleted file mode 100644 index 0c2838600c..0000000000 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/outgoing/FakeAccountOutgoingConfigViewModel.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.k9mail.feature.account.setup.ui.outgoing - -import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.setup.ui.outgoing.AccountOutgoingConfigContract.ViewModel - -class FakeAccountOutgoingConfigViewModel( - initialState: State = State(), -) : BaseViewModel(initialState), ViewModel { - - val events = mutableListOf() - - override fun event(event: Event) { - events.add(event) - } - - fun effect(effect: Effect) { - emitEffect(effect) - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 4c7e49384a..63a7f0fb68 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -48,6 +48,7 @@ include( ":feature:account:oauth", ":feature:account:setup", ":feature:account:server:certificate", + ":feature:account:server:config", ":feature:account:server:validation", ) -- GitLab From 826588e0c23a6ed6967a6416af426a92d5b7a7c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 14:39:46 +0200 Subject: [PATCH 20/94] Rename AutoDiscoveryStatus to AutoDiscoveryResult --- .../AccountAutoDiscoveryContract.kt | 2 +- .../AccountAutoDiscoveryViewModel.kt | 2 +- .../AutoDiscoveryStringMapper.kt | 2 +- ....kt => AutoDiscoveryResultApprovalItem.kt} | 10 ++--- ...atusItem.kt => AutoDiscoveryResultItem.kt} | 6 +-- .../ui/autodiscovery/item/ContentItems.kt | 8 ++-- ....kt => AutoDiscoveryResultApprovalView.kt} | 24 +++++++++-- ...View.kt => AutoDiscoveryResultBodyView.kt} | 10 ++--- ...e.kt => AutoDiscoveryResultHeaderState.kt} | 10 ++--- ...ew.kt => AutoDiscoveryResultHeaderView.kt} | 42 +++++++++---------- ...atusView.kt => AutoDiscoveryResultView.kt} | 20 ++++----- .../setup/src/main/res/values/strings.xml | 16 +++---- .../AccountAutoDiscoveryViewModelTest.kt | 4 +- 13 files changed, 86 insertions(+), 70 deletions(-) rename feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/{ConfigurationApprovalItem.kt => AutoDiscoveryResultApprovalItem.kt} (63%) rename feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/{AutoDiscoveryStatusItem.kt => AutoDiscoveryResultItem.kt} (86%) rename feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/{ConfigurationApprovalView.kt => AutoDiscoveryResultApprovalView.kt} (62%) rename feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/{AutoDiscoveryStatusBodyView.kt => AutoDiscoveryResultBodyView.kt} (94%) rename feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/{AutoDiscoveryStatusHeaderState.kt => AutoDiscoveryResultHeaderState.kt} (82%) rename feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/{AutoDiscoveryStatusHeaderView.kt => AutoDiscoveryResultHeaderView.kt} (70%) rename feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/{AutoDiscoveryStatusView.kt => AutoDiscoveryResultView.kt} (89%) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt index e7a0ca443b..287bfdae1c 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContract.kt @@ -41,7 +41,7 @@ interface AccountAutoDiscoveryContract { sealed interface Event { data class EmailAddressChanged(val emailAddress: String) : Event data class PasswordChanged(val password: String) : Event - data class ConfigurationApprovalChanged(val confirmed: Boolean) : Event + data class ResultApprovalChanged(val confirmed: Boolean) : Event data class OnOAuthResult(val result: OAuthResult) : Event object OnNextClicked : Event diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt index ec2f920bfa..8aad922fb3 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt @@ -38,7 +38,7 @@ internal class AccountAutoDiscoveryViewModel( when (event) { is Event.EmailAddressChanged -> changeEmailAddress(event.emailAddress) is Event.PasswordChanged -> changePassword(event.password) - is Event.ConfigurationApprovalChanged -> changeConfigurationApproval(event.confirmed) + is Event.ResultApprovalChanged -> changeConfigurationApproval(event.confirmed) is Event.OnOAuthResult -> onOAuthResult(event.result) Event.OnNextClicked -> onNext() diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt index 33823b6c4d..d942016e7f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt @@ -40,7 +40,7 @@ private fun ValidateConfigurationApproval.ValidateConfigurationApprovalError.toC ): String { return when (this) { ValidateConfigurationApproval.ValidateConfigurationApprovalError.ApprovalRequired -> resources.getString( - R.string.account_setup_auto_discovery_error_configuration_approval_required, + R.string.account_setup_auto_discovery_result_approval_error_approval_required, ) } } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ConfigurationApprovalItem.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/AutoDiscoveryResultApprovalItem.kt similarity index 63% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ConfigurationApprovalItem.kt rename to feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/AutoDiscoveryResultApprovalItem.kt index ed1bdb6ad7..7a98900024 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ConfigurationApprovalItem.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/AutoDiscoveryResultApprovalItem.kt @@ -5,20 +5,20 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import app.k9mail.feature.account.common.domain.input.BooleanInputField import app.k9mail.feature.account.common.ui.item.ListItem -import app.k9mail.feature.account.setup.ui.autodiscovery.view.ConfigurationApprovalView +import app.k9mail.feature.account.setup.ui.autodiscovery.view.AutoDiscoveryResultApprovalView @Composable -internal fun LazyItemScope.ConfigurationApprovalItem( +internal fun LazyItemScope.AutoDiscoveryResultApprovalItem( approvalState: BooleanInputField, - onConfigurationApprovalChange: (Boolean) -> Unit, + onApprovalChange: (Boolean) -> Unit, modifier: Modifier = Modifier, ) { ListItem( modifier = modifier, ) { - ConfigurationApprovalView( + AutoDiscoveryResultApprovalView( approvalState = approvalState, - onConfigurationApprovalChange = onConfigurationApprovalChange, + onApprovalChange = onApprovalChange, ) } } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/AutoDiscoveryStatusItem.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/AutoDiscoveryResultItem.kt similarity index 86% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/AutoDiscoveryStatusItem.kt rename to feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/AutoDiscoveryResultItem.kt index 532ac67e93..bc550dfe9b 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/AutoDiscoveryStatusItem.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/AutoDiscoveryResultItem.kt @@ -5,10 +5,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import app.k9mail.autodiscovery.api.AutoDiscoveryResult import app.k9mail.feature.account.common.ui.item.ListItem -import app.k9mail.feature.account.setup.ui.autodiscovery.view.AutoDiscoveryStatusView +import app.k9mail.feature.account.setup.ui.autodiscovery.view.AutoDiscoveryResultView @Composable -internal fun LazyItemScope.AutoDiscoveryStatusItem( +internal fun LazyItemScope.AutoDiscoveryResultItem( autoDiscoverySettings: AutoDiscoveryResult.Settings?, onEditConfigurationClick: () -> Unit, modifier: Modifier = Modifier, @@ -16,7 +16,7 @@ internal fun LazyItemScope.AutoDiscoveryStatusItem( ListItem( modifier = modifier, ) { - AutoDiscoveryStatusView( + AutoDiscoveryResultView( settings = autoDiscoverySettings, onEditConfigurationClick = onEditConfigurationClick, ) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ContentItems.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ContentItems.kt index 331a153a2c..bf6c92e495 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ContentItems.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/ContentItems.kt @@ -15,16 +15,16 @@ internal fun LazyListScope.contentItems( ) { if (state.configStep != ConfigStep.EMAIL_ADDRESS) { item(key = "autodiscovery") { - AutoDiscoveryStatusItem( + AutoDiscoveryResultItem( autoDiscoverySettings = state.autoDiscoverySettings, onEditConfigurationClick = { onEvent(Event.OnEditConfigurationClicked) }, ) } if (state.autoDiscoverySettings != null && state.autoDiscoverySettings.isTrusted.not()) { - item(key = "config_approval") { - ConfigurationApprovalItem( + item(key = "result_approval") { + AutoDiscoveryResultApprovalItem( approvalState = state.configurationApproved, - onConfigurationApprovalChange = { onEvent(Event.ConfigurationApprovalChanged(it)) }, + onApprovalChange = { onEvent(Event.ResultApprovalChanged(it)) }, ) } } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultApprovalView.kt similarity index 62% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt rename to feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultApprovalView.kt index 1857ea4c42..b1ab4bc1c5 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/ConfigurationApprovalView.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultApprovalView.kt @@ -7,16 +7,18 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import app.k9mail.core.ui.compose.designsystem.molecule.input.CheckboxInput import app.k9mail.core.ui.compose.theme.MainTheme +import app.k9mail.core.ui.compose.theme.PreviewWithThemes import app.k9mail.feature.account.common.domain.input.BooleanInputField import app.k9mail.feature.account.setup.R import app.k9mail.feature.account.setup.ui.autodiscovery.toResourceString @Composable -internal fun ConfigurationApprovalView( +internal fun AutoDiscoveryResultApprovalView( approvalState: BooleanInputField, - onConfigurationApprovalChange: (Boolean) -> Unit, + onApprovalChange: (Boolean) -> Unit, ) { val resources = LocalContext.current.resources @@ -24,11 +26,25 @@ internal fun ConfigurationApprovalView( CheckboxInput( text = stringResource( - id = R.string.account_setup_auto_discovery_status_checkbox_configuration_untrusted_confirmation_label, + id = R.string.account_setup_auto_discovery_result_approval_checkbox_label, ), checked = approvalState.value ?: false, - onCheckedChange = onConfigurationApprovalChange, + onCheckedChange = onApprovalChange, errorMessage = approvalState.error?.toResourceString(resources), contentPadding = PaddingValues(), ) } + +@Preview(showBackground = true) +@Composable +internal fun AutoDiscoveryResultApprovalViewPreview() { + PreviewWithThemes { + AutoDiscoveryResultApprovalView( + approvalState = BooleanInputField( + value = true, + isValid = true, + ), + onApprovalChange = {}, + ) + } +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusBodyView.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultBodyView.kt similarity index 94% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusBodyView.kt rename to feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultBodyView.kt index 9f9377ee28..edc2cc1157 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusBodyView.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultBodyView.kt @@ -26,7 +26,7 @@ import app.k9mail.core.ui.compose.theme.PreviewWithThemes import app.k9mail.feature.account.setup.R @Composable -internal fun AutoDiscoveryStatusBodyView( +internal fun AutoDiscoveryResultBodyView( settings: AutoDiscoveryResult.Settings, onEditConfigurationClick: () -> Unit, modifier: Modifier = Modifier, @@ -42,7 +42,7 @@ internal fun AutoDiscoveryStatusBodyView( Spacer(modifier = Modifier.height(MainTheme.sizes.smaller)) TextBody2( text = stringResource( - id = R.string.account_setup_auto_discovery_status_disclaimer_untrusted_configuration, + id = R.string.account_setup_auto_discovery_result_disclaimer_untrusted_configuration, ), modifier = Modifier.fillMaxWidth(), ) @@ -94,7 +94,7 @@ internal fun EditConfigurationButton( .then(modifier), ) { ButtonText( - text = stringResource(id = R.string.account_setup_auto_discovery_status_edit_configuration_button_label), + text = stringResource(id = R.string.account_setup_auto_discovery_result_edit_configuration_button_label), onClick = onEditConfigurationClick, color = MainTheme.colors.warning, contentPadding = buttonContentPadding( @@ -107,9 +107,9 @@ internal fun EditConfigurationButton( @Preview @Composable -internal fun AutoDiscoveryStatusBodyViewPreview() { +internal fun AutoDiscoveryResultBodyViewPreview() { PreviewWithThemes { - AutoDiscoveryStatusBodyView( + AutoDiscoveryResultBodyView( settings = AutoDiscoveryResult.Settings( incomingServerSettings = ImapServerSettings( hostname = "imap.example.com".toHostname(), diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusHeaderState.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultHeaderState.kt similarity index 82% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusHeaderState.kt rename to feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultHeaderState.kt index 54a727234e..8a6cf132be 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusHeaderState.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultHeaderState.kt @@ -5,7 +5,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import app.k9mail.core.ui.compose.theme.Icons import app.k9mail.feature.account.setup.R -enum class AutoDiscoveryStatusHeaderState( +enum class AutoDiscoveryResultHeaderState( val icon: ImageVector, @StringRes val titleResourceId: Int, @StringRes val subtitleResourceId: Int, @@ -13,22 +13,22 @@ enum class AutoDiscoveryStatusHeaderState( ) { NoSettings( icon = Icons.Outlined.info, - titleResourceId = R.string.account_setup_auto_discovery_status_header_title_configuration_not_found, - subtitleResourceId = R.string.account_setup_auto_discovery_status_header_subtitle_configuration_not_found, + titleResourceId = R.string.account_setup_auto_discovery_result_header_title_configuration_not_found, + subtitleResourceId = R.string.account_setup_auto_discovery_result_header_subtitle_configuration_not_found, isExpandable = false, ), Trusted( icon = Icons.Outlined.check, titleResourceId = R.string.account_setup_auto_discovery_status_header_title_configuration_found, - subtitleResourceId = R.string.account_setup_auto_discovery_status_header_subtitle_configuration_trusted, + subtitleResourceId = R.string.account_setup_auto_discovery_result_header_subtitle_configuration_trusted, isExpandable = true, ), Untrusted( icon = Icons.Outlined.info, titleResourceId = R.string.account_setup_auto_discovery_status_header_title_configuration_found, - subtitleResourceId = R.string.account_setup_auto_discovery_status_header_subtitle_configuration_untrusted, + subtitleResourceId = R.string.account_setup_auto_discovery_result_header_subtitle_configuration_untrusted, isExpandable = true, ), } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusHeaderView.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultHeaderView.kt similarity index 70% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusHeaderView.kt rename to feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultHeaderView.kt index 31c5906027..8bfd4c3d41 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusHeaderView.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultHeaderView.kt @@ -20,8 +20,8 @@ import app.k9mail.core.ui.compose.theme.PreviewWithThemes @Suppress("LongMethod") @Composable -internal fun AutoDiscoveryStatusHeaderView( - state: AutoDiscoveryStatusHeaderState, +internal fun AutoDiscoveryResultHeaderView( + state: AutoDiscoveryResultHeaderState, isExpanded: Boolean, modifier: Modifier = Modifier, ) { @@ -65,20 +65,20 @@ internal fun AutoDiscoveryStatusHeaderView( } @Composable -private fun selectColor(state: AutoDiscoveryStatusHeaderState): Color { +private fun selectColor(state: AutoDiscoveryResultHeaderState): Color { return when (state) { - AutoDiscoveryStatusHeaderState.NoSettings -> MainTheme.colors.primary - AutoDiscoveryStatusHeaderState.Trusted -> MainTheme.colors.success - AutoDiscoveryStatusHeaderState.Untrusted -> MainTheme.colors.warning + AutoDiscoveryResultHeaderState.NoSettings -> MainTheme.colors.primary + AutoDiscoveryResultHeaderState.Trusted -> MainTheme.colors.success + AutoDiscoveryResultHeaderState.Untrusted -> MainTheme.colors.warning } } @Preview @Composable -internal fun AutoDiscoveryStatusHeaderViewTrustedCollapsedPreview() { +internal fun AutoDiscoveryResultHeaderViewTrustedCollapsedPreview() { PreviewWithThemes { - AutoDiscoveryStatusHeaderView( - state = AutoDiscoveryStatusHeaderState.Trusted, + AutoDiscoveryResultHeaderView( + state = AutoDiscoveryResultHeaderState.Trusted, isExpanded = true, ) } @@ -86,10 +86,10 @@ internal fun AutoDiscoveryStatusHeaderViewTrustedCollapsedPreview() { @Preview @Composable -internal fun AutoDiscoveryStatusHeaderViewTrustedExpandedPreview() { +internal fun AutoDiscoveryResultHeaderViewTrustedExpandedPreview() { PreviewWithThemes { - AutoDiscoveryStatusHeaderView( - state = AutoDiscoveryStatusHeaderState.Trusted, + AutoDiscoveryResultHeaderView( + state = AutoDiscoveryResultHeaderState.Trusted, isExpanded = false, ) } @@ -97,10 +97,10 @@ internal fun AutoDiscoveryStatusHeaderViewTrustedExpandedPreview() { @Preview @Composable -internal fun AutoDiscoveryStatusHeaderViewUntrustedCollapsedPreview() { +internal fun AutoDiscoveryResultHeaderViewUntrustedCollapsedPreview() { PreviewWithThemes { - AutoDiscoveryStatusHeaderView( - state = AutoDiscoveryStatusHeaderState.Untrusted, + AutoDiscoveryResultHeaderView( + state = AutoDiscoveryResultHeaderState.Untrusted, isExpanded = true, ) } @@ -108,10 +108,10 @@ internal fun AutoDiscoveryStatusHeaderViewUntrustedCollapsedPreview() { @Preview @Composable -internal fun AutoDiscoveryStatusHeaderViewUntrustedExpandedPreview() { +internal fun AutoDiscoveryResultHeaderViewUntrustedExpandedPreview() { PreviewWithThemes { - AutoDiscoveryStatusHeaderView( - state = AutoDiscoveryStatusHeaderState.Untrusted, + AutoDiscoveryResultHeaderView( + state = AutoDiscoveryResultHeaderState.Untrusted, isExpanded = false, ) } @@ -119,10 +119,10 @@ internal fun AutoDiscoveryStatusHeaderViewUntrustedExpandedPreview() { @Preview @Composable -internal fun AutoDiscoveryStatusHeaderNoSettingsPreview() { +internal fun AutoDiscoveryResultHeaderNoSettingsPreview() { PreviewWithThemes { - AutoDiscoveryStatusHeaderView( - state = AutoDiscoveryStatusHeaderState.NoSettings, + AutoDiscoveryResultHeaderView( + state = AutoDiscoveryResultHeaderState.NoSettings, isExpanded = false, ) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusView.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultView.kt similarity index 89% rename from feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusView.kt rename to feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultView.kt index 4d840f2b9f..5096b99a47 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryStatusView.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/view/AutoDiscoveryResultView.kt @@ -24,7 +24,7 @@ import app.k9mail.core.ui.compose.theme.MainTheme import app.k9mail.core.ui.compose.theme.PreviewWithThemes @Composable -internal fun AutoDiscoveryStatusView( +internal fun AutoDiscoveryResultView( settings: AutoDiscoveryResult.Settings?, onEditConfigurationClick: () -> Unit, modifier: Modifier = Modifier, @@ -47,20 +47,20 @@ internal fun AutoDiscoveryStatusView( Column( modifier = Modifier.padding(MainTheme.spacings.default), ) { - AutoDiscoveryStatusHeaderView( + AutoDiscoveryResultHeaderView( state = if (settings == null) { - AutoDiscoveryStatusHeaderState.NoSettings + AutoDiscoveryResultHeaderState.NoSettings } else if (settings.isTrusted) { - AutoDiscoveryStatusHeaderState.Trusted + AutoDiscoveryResultHeaderState.Trusted } else { - AutoDiscoveryStatusHeaderState.Untrusted + AutoDiscoveryResultHeaderState.Untrusted }, isExpanded = expanded.value, ) if (settings != null) { AnimatedVisibility(visible = expanded.value) { - AutoDiscoveryStatusBodyView( + AutoDiscoveryResultBodyView( settings = settings, onEditConfigurationClick = onEditConfigurationClick, ) @@ -73,9 +73,9 @@ internal fun AutoDiscoveryStatusView( @Preview(showBackground = true) @Composable -internal fun AutoDiscoveryStatusViewTrustedPreview() { +internal fun AutoDiscoveryResultViewTrustedPreview() { PreviewWithThemes { - AutoDiscoveryStatusView( + AutoDiscoveryResultView( settings = AutoDiscoveryResult.Settings( incomingServerSettings = ImapServerSettings( hostname = "imap.example.com".toHostname(), @@ -101,9 +101,9 @@ internal fun AutoDiscoveryStatusViewTrustedPreview() { @Preview(showBackground = true) @Composable -internal fun AutoDiscoveryStatusViewUntrustedPreview() { +internal fun AutoDiscoveryResultViewUntrustedPreview() { PreviewWithThemes { - AutoDiscoveryStatusView( + AutoDiscoveryResultView( settings = AutoDiscoveryResult.Settings( incomingServerSettings = ImapServerSettings( hostname = "imap.example.com".toHostname(), diff --git a/feature/account/setup/src/main/res/values/strings.xml b/feature/account/setup/src/main/res/values/strings.xml index 21cc780041..9eaa60965e 100644 --- a/feature/account/setup/src/main/res/values/strings.xml +++ b/feature/account/setup/src/main/res/values/strings.xml @@ -11,14 +11,14 @@ Finding email details Failed to load email configuration Configuration Found - Configuration Not Found - Configure automatically - This configuration is not trusted - We received the configuration for your email server over a connection that isn\'t as secure as we\'d like. This means that there is a tiny chance that someone could have altered it. Could you please double-check the provided configuration to make sure it\'s as it should be? - Configure manually - Edit configuration - I trust this configuration - It is required to approve the configuration. + Configuration Not Found + Configure automatically + This configuration is not trusted + We received the configuration for your email server over a connection that isn\'t as secure as we\'d like. This means that there is a tiny chance that someone could have altered it. Could you please double-check the provided configuration to make sure it\'s as it should be? + Configure manually + Edit configuration + I trust this configuration + It is required to approve the configuration. Account options Display options diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt index 0d38937df4..25919b68fa 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModelTest.kt @@ -67,11 +67,11 @@ class AccountAutoDiscoveryViewModelTest { } @Test - fun `should change state when ConfigurationApprovalChanged event is received`() = runTest { + fun `should change state when ResultApprovalChanged event is received`() = runTest { eventStateTest( viewModel = createTestSubject(), initialState = State(), - event = Event.ConfigurationApprovalChanged(true), + event = Event.ResultApprovalChanged(true), expectedState = State( configurationApproved = BooleanInputField(value = true), ), -- GitLab From 1fe926fad4cfbce2f4e431bb26d1bedf7b420633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 15:24:46 +0200 Subject: [PATCH 21/94] Bump Gradle 8.1.1 -> 8.3 --- app/k9mail/build.gradle.kts | 2 +- gradle.properties | 3 ++- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 3 ++- gradlew | 8 ++++++-- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/k9mail/build.gradle.kts b/app/k9mail/build.gradle.kts index 4e8618fd5b..fd0f33f511 100644 --- a/app/k9mail/build.gradle.kts +++ b/app/k9mail/build.gradle.kts @@ -150,7 +150,7 @@ android { } } - packagingOptions { + packaging { jniLibs { excludes += listOf("kotlin/**") } diff --git a/gradle.properties b/gradle.properties index 9cd50e7260..4aaff1c8bc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,6 +9,7 @@ android.useAndroidX=true android.enableJetifier=false android.nonTransitiveRClass=true -org.gradle.jvmargs=-Xmx3g -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8 org.gradle.parallel=true org.gradle.caching=true +org.gradle.kotlin.dsl.allWarningsAsErrors=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2aadb2544e..2520c65b2b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ # Please don't open pull requests upgrading dependencies if you're a new contributor. [versions] -gradle = "8.1.1" +gradle = "8.3" androidGradlePlugin = "8.0.2" ktlint = "0.48.2" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch delta 37652 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 delta 36122 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 Ac-xW1# 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 Q>rd#Eb%7 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8707e8b506..d11cdd907d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cbb43..0adc8e1a53 100755 --- a/gradlew +++ b/gradlew @@ -83,7 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -130,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -- GitLab From 95b9d747b1701da436fcf2690c195f850726db6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 17:04:01 +0200 Subject: [PATCH 22/94] Bump dependencies Kotlin 1.8.21 -> 1.8.22 KotlinX Coroutines 1.7.1 -> 1.7.3 KotlinX DateTime 0.4.0 -> 0.4.1 AndroidX RecyclerView 1.3.0 -> 1.3.1 AndroidX Fragment 1.6.0 -> 1.6.1 AndroidX Preference 1.2.0 -> 1.2.1 AndroidX Compose Compiler 1.4.7 -> 1.4.8 AndroidX Compose BOM 2023.05.01 -> 2034.06.01 Koin 3.4.2 -> 3.5.3 Koin Compose 3.4.5 -> 3.4.6 Glide 4.15.1 -> 4.16.0 KSP 1.8.21-1.0.11 -> 1.8.22-1.0.11 Okio 3.3.0 -> 3.4.0 --- gradle/libs.versions.toml | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2520c65b2b..72f046d79b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,35 +6,36 @@ gradle = "8.3" androidGradlePlugin = "8.0.2" ktlint = "0.48.2" -kotlin = "1.8.21" -kotlinxCoroutines = "1.7.1" +kotlin = "1.8.22" +kotlinxCoroutines = "1.7.3" jetbrainsAnnotations = "24.0.1" androidxAppCompat = "1.6.1" androidxActivity = "1.7.2" -androidxRecyclerView = "1.3.0" +androidxRecyclerView = "1.3.1" androidxLifecycle = "2.6.1" androidxNavigation = "2.6.0" androidxConstraintLayout = "2.1.4" -androidxFragment = "1.6.0" +androidxFragment = "1.6.1" androidxCore = "1.10.1" androidxCoreSplashscreen = "1.0.1" -androidxPreference = "1.2.0" +androidxPreference = "1.2.1" androidxDrawerLayout = "1.1.1" androidxTransition = "1.4.1" -androidxComposeCompiler = "1.4.7" -androidxComposeBom = "2023.05.01" +androidxComposeCompiler = "1.4.8" +# https://developer.android.com/jetpack/compose/bom/bom-mapping +androidxComposeBom = "2023.06.01" androidxComposeMaterial = "1.4.3" accompanist = "0.30.1" fastAdapter = "5.7.0" preferencesFix = "1.1.0" timber = "5.0.1" -koinCore = "3.4.2" -koinAndroid = "3.4.2" -koinAndroidCompose = "3.4.5" -koinTest = "3.4.1" +koinCore = "3.4.3" +koinAndroid = "3.4.3" +koinAndroidCompose = "3.4.6" +koinTest = "3.4.3" mime4j = "0.8.9" okhttp = "4.11.0" -glide = "4.15.1" +glide = "4.16.0" moshi = "1.15.0" mockito = "5.3.1" @@ -42,7 +43,7 @@ mockito = "5.3.1" android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } android-lint = { id = "com.android.lint", version.ref = "androidGradlePlugin" } -ksp = "com.google.devtools.ksp:1.8.21-1.0.11" +ksp = "com.google.devtools.ksp:1.8.22-1.0.11" kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } @@ -58,7 +59,7 @@ kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" } kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutines" } kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" } -kotlinx-datetime = "org.jetbrains.kotlinx:kotlinx-datetime:0.4.0" +kotlinx-datetime = "org.jetbrains.kotlinx:kotlinx-datetime:0.4.1" kotlinx-collections-immutable = "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.5" jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrainsAnnotations" } androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidxAppCompat" } @@ -107,7 +108,7 @@ materialdrawer = "com.mikepenz:materialdrawer:8.4.5" preferencex = { module = "com.takisoft.preferencex:preferencex", version.ref = "preferencesFix" } preferencex-datetimepicker = { module = "com.takisoft.preferencex:preferencex-datetimepicker", version.ref = "preferencesFix" } preferencex-colorpicker = { module = "com.takisoft.preferencex:preferencex-colorpicker", version.ref = "preferencesFix" } -okio = "com.squareup.okio:okio:3.3.0" +okio = "com.squareup.okio:okio:3.4.0" moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" } moshi-kotlin-codegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi" } timber = "com.jakewharton.timber:timber:5.0.1" -- GitLab From 2e886a72551e204a4b0adff3ac970a506755f7d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 17:04:45 +0200 Subject: [PATCH 23/94] Bump Mockito 5.3.1 -> 5.4.0 and Mockito Kotlin 4.1.0 -> 5.1.0 --- .../java/com/fsck/k9/mailstore/MessageStoreManagerTest.kt | 2 +- app/testing/src/main/java/com/fsck/k9/testing/MockHelper.kt | 2 +- gradle/libs.versions.toml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/core/src/test/java/com/fsck/k9/mailstore/MessageStoreManagerTest.kt b/app/core/src/test/java/com/fsck/k9/mailstore/MessageStoreManagerTest.kt index 98c59cb9a2..89d5e2f626 100644 --- a/app/core/src/test/java/com/fsck/k9/mailstore/MessageStoreManagerTest.kt +++ b/app/core/src/test/java/com/fsck/k9/mailstore/MessageStoreManagerTest.kt @@ -45,7 +45,7 @@ class MessageStoreManagerTest { assertThat(messageStoreManager.getMessageStore(account)).isSameAs(messageStore2) } - private fun KStubbing.doNothingOn(block: T.() -> Any) { + private fun KStubbing.doNothingOn(block: T.() -> Any) { doNothing().whenever(mock).block() } } diff --git a/app/testing/src/main/java/com/fsck/k9/testing/MockHelper.kt b/app/testing/src/main/java/com/fsck/k9/testing/MockHelper.kt index 17e9e6986e..32bca4f250 100644 --- a/app/testing/src/main/java/com/fsck/k9/testing/MockHelper.kt +++ b/app/testing/src/main/java/com/fsck/k9/testing/MockHelper.kt @@ -17,7 +17,7 @@ object MockHelper { } } - inline fun mockBuilder(stubbing: KStubbing.(T) -> Unit = {}): T { + inline fun mockBuilder(stubbing: KStubbing.(T) -> Unit = {}): T { return mockBuilder(T::class.java).apply { KStubbing(this).stubbing(this) } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 72f046d79b..3bd6f716d2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -37,7 +37,7 @@ mime4j = "0.8.9" okhttp = "4.11.0" glide = "4.16.0" moshi = "1.15.0" -mockito = "5.3.1" +mockito = "5.4.0" [plugins] android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } @@ -144,7 +144,7 @@ kxml2 = "com.github.cketti:kxml2-extracted-from-android:1.0" junit = "junit:junit:4.13.2" robolectric = "org.robolectric:robolectric:4.9.2" mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" } -mockito-kotlin = "org.mockito.kotlin:mockito-kotlin:4.1.0" +mockito-kotlin = "org.mockito.kotlin:mockito-kotlin:5.1.0" turbine = "app.cash.turbine:turbine:0.13.0" jdom2 = "org.jdom:jdom2:2.0.6.1" icu4j-charset = "com.ibm.icu:icu4j-charset:72.1" -- GitLab From 5357f308f6ee871f08986e20a4c9c06a85e7fe9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 17:06:42 +0200 Subject: [PATCH 24/94] Bump Detekt Compose plugin 0.1.7 to 0.1.11 --- .../ui/catalog/ui/common/drawer/DrawerCategoryItem.kt | 2 +- .../k9mail/ui/catalog/ui/common/drawer/DrawerHeaderItem.kt | 2 +- .../compose/designsystem/atom/textfield/TextFieldCommon.kt | 6 +++--- gradle/libs.versions.toml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/drawer/DrawerCategoryItem.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/drawer/DrawerCategoryItem.kt index a04959d942..4cd6b5cc1b 100644 --- a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/drawer/DrawerCategoryItem.kt +++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/drawer/DrawerCategoryItem.kt @@ -35,7 +35,7 @@ fun DrawerCategoryItem( @Preview @Composable -fun DrawerCategoryItemPreview() { +internal fun DrawerCategoryItemPreview() { PreviewWithThemes { DrawerCategoryItem( text = "Text", diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/drawer/DrawerHeaderItem.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/drawer/DrawerHeaderItem.kt index d176eb5372..0b1f6cc162 100644 --- a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/drawer/DrawerHeaderItem.kt +++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/drawer/DrawerHeaderItem.kt @@ -35,7 +35,7 @@ fun DrawerHeaderItem( @Preview @Composable -fun DrawerHeaderItemPreview() { +internal fun DrawerHeaderItemPreview() { PreviewWithThemes { DrawerHeaderItem( text = "Category", diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/atom/textfield/TextFieldCommon.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/atom/textfield/TextFieldCommon.kt index fcf3cb0121..f34727a973 100644 --- a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/atom/textfield/TextFieldCommon.kt +++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/atom/textfield/TextFieldCommon.kt @@ -36,7 +36,7 @@ private const val ASTERISK = "*" @Preview(showBackground = true) @Composable -fun TextFieldLabelPreview() { +internal fun TextFieldLabelPreview() { PreviewWithThemes { TextFieldLabel( label = "Label", @@ -47,7 +47,7 @@ fun TextFieldLabelPreview() { @Preview(showBackground = true) @Composable -fun TextFieldLabelRequiredPreview() { +internal fun TextFieldLabelRequiredPreview() { PreviewWithThemes { TextFieldLabel( label = "Label", @@ -58,7 +58,7 @@ fun TextFieldLabelRequiredPreview() { @Preview(showBackground = true) @Composable -fun TextFieldLabelRequiredEmptyLabelPreview() { +internal fun TextFieldLabelRequiredEmptyLabelPreview() { PreviewWithThemes { TextFieldLabel( label = "", diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3bd6f716d2..23925c92b9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -152,7 +152,7 @@ assertk = "com.willowtreeapps.assertk:assertk-jvm:0.26.1" leakcanary-android = "com.squareup.leakcanary:leakcanary-android:2.9.1" -detekt-plugin-compose = "io.nlopez.compose.rules:detekt:0.1.7" +detekt-plugin-compose = "io.nlopez.compose.rules:detekt:0.1.11" [bundles] shared-jvm-main = [ -- GitLab From d31737923d114fc7037e420b079cb6dcc234780e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 17:09:45 +0200 Subject: [PATCH 25/94] Add Compose Material3 dependency --- gradle/libs.versions.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 23925c92b9..669bb03152 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,6 +25,7 @@ androidxComposeCompiler = "1.4.8" # https://developer.android.com/jetpack/compose/bom/bom-mapping androidxComposeBom = "2023.06.01" androidxComposeMaterial = "1.4.3" +androidxComposeMaterial3 = "1.1.1" accompanist = "0.30.1" fastAdapter = "5.7.0" preferencesFix = "1.1.0" @@ -94,6 +95,8 @@ androidx-compose-activity = { module = "androidx.activity:activity-compose", ver androidx-compose-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidxLifecycle" } androidx-compose-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidxLifecycle" } androidx-compose-material = { module = "androidx.compose.material:material", version.ref = "androidxComposeMaterial" } +androidx-compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "androidxComposeMaterial3" } +androidx-compose-material3-windowSizeClass = { module = "androidx.compose.material3:material3-window-size-class", version.ref = "androidxComposeMaterial3" } androidx-compose-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "androidxComposeMaterial" } androidx-compose-navigation = { module = "androidx.navigation:navigation-compose", version.ref = "androidxNavigation" } androidx-test-core = "androidx.test:core:1.5.0" -- GitLab From e9535ecdaa79a28d68bc287cf383fcf8328990c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 17:55:46 +0200 Subject: [PATCH 26/94] Bump Spotless 6.14.0 -> 6.21.0 and KtLint 0.48.2 -> 0.50.0, and reformat/fix code --- app/core/src/main/java/com/fsck/k9/K9.kt | 1 + .../fsck/k9/notification/NotificationIds.kt | 3 +- .../MessageViewContainerFragment.kt | 4 +-- .../thunderbird.quality.spotless.gradle.kts | 1 + .../k9mail/core/common/net/HostNameUtils.kt | 4 +-- gradle/libs.versions.toml | 4 +-- .../k9/mail/internet/MimeHeaderEncoder.kt | 4 ++- .../k9/mail/internet/MimeParameterEncoder.kt | 18 ++++++++---- .../k9/mail/internet/MimeHeaderCheckerTest.kt | 29 +++++++++++++------ .../fsck/k9/mail/store/imap/RealImapFolder.kt | 3 +- 10 files changed, 47 insertions(+), 24 deletions(-) diff --git a/app/core/src/main/java/com/fsck/k9/K9.kt b/app/core/src/main/java/com/fsck/k9/K9.kt index c47101cc81..5951dc60f4 100644 --- a/app/core/src/main/java/com/fsck/k9/K9.kt +++ b/app/core/src/main/java/com/fsck/k9/K9.kt @@ -505,6 +505,7 @@ object K9 : EarlyInit { const val MAIL_SERVICE_WAKE_LOCK_TIMEOUT = 60000 const val BOOT_RECEIVER_WAKE_LOCK_TIMEOUT = 60000 + @Suppress("ktlint:standard:class-naming") enum class BACKGROUND_OPS { ALWAYS, NEVER, WHEN_CHECKED_AUTO_SYNC } diff --git a/app/core/src/main/java/com/fsck/k9/notification/NotificationIds.kt b/app/core/src/main/java/com/fsck/k9/notification/NotificationIds.kt index daaa105c06..3daf4f438b 100644 --- a/app/core/src/main/java/com/fsck/k9/notification/NotificationIds.kt +++ b/app/core/src/main/java/com/fsck/k9/notification/NotificationIds.kt @@ -59,7 +59,8 @@ internal object NotificationIds { } private fun getBaseNotificationId(account: Account): Int { - return 1 /* skip notification ID 0 */ + NUMBER_OF_GENERAL_NOTIFICATIONS + + /* skip notification ID 0 */ + return 1 + NUMBER_OF_GENERAL_NOTIFICATIONS + account.accountNumber * NUMBER_OF_NOTIFICATIONS_PER_ACCOUNT } } diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/MessageViewContainerFragment.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/MessageViewContainerFragment.kt index 848d8089fc..84de6c46dc 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/MessageViewContainerFragment.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/MessageViewContainerFragment.kt @@ -184,7 +184,7 @@ class MessageViewContainerFragment : Fragment() { val newPosition = viewPager.currentItem - 1 return if (newPosition >= 0) { setActiveMessage(newPosition) - viewPager.setCurrentItem(newPosition, /* smoothScroll = */ false) + viewPager.setCurrentItem(newPosition, false) true } else { false @@ -195,7 +195,7 @@ class MessageViewContainerFragment : Fragment() { val newPosition = viewPager.currentItem + 1 return if (newPosition < adapter.itemCount) { setActiveMessage(newPosition) - viewPager.setCurrentItem(newPosition, /* smoothScroll = */ false) + viewPager.setCurrentItem(newPosition, false) true } else { false diff --git a/build-plugin/src/main/kotlin/thunderbird.quality.spotless.gradle.kts b/build-plugin/src/main/kotlin/thunderbird.quality.spotless.gradle.kts index d799629a7c..e59057cb4b 100644 --- a/build-plugin/src/main/kotlin/thunderbird.quality.spotless.gradle.kts +++ b/build-plugin/src/main/kotlin/thunderbird.quality.spotless.gradle.kts @@ -7,6 +7,7 @@ plugins { configure { kotlin { ktlint(libs.versions.ktlint.get()) + .userData(mapOf("android" to "true")) target("**/*.kt") targetExclude("**/build/", "**/resources/", "plugins/openpgp-api-lib/") } diff --git a/core/common/src/main/kotlin/app/k9mail/core/common/net/HostNameUtils.kt b/core/common/src/main/kotlin/app/k9mail/core/common/net/HostNameUtils.kt index 91e1f2ba3a..d8e7729aca 100644 --- a/core/common/src/main/kotlin/app/k9mail/core/common/net/HostNameUtils.kt +++ b/core/common/src/main/kotlin/app/k9mail/core/common/net/HostNameUtils.kt @@ -24,7 +24,7 @@ object HostNameUtils { address in dotted-decimal ("#.#.#.#") form. The host SHOULD check the string syntactically for a dotted-decimal number before looking it up in the Domain Name System. - */ + */ return isLegalIPAddress(hostName) ?: isLegalHostName(hostName) } @@ -204,7 +204,7 @@ object HostNameUtils { Since a complete domain name ends with the root label, this leads to a printed form which ends in a dot. - */ + */ return hostName.takeIf { hostName.length <= 255 && HOST_PATTERN.matches(hostName) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 669bb03152..aed59613cf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ [versions] gradle = "8.3" androidGradlePlugin = "8.0.2" -ktlint = "0.48.2" +ktlint = "0.50.0" kotlin = "1.8.22" kotlinxCoroutines = "1.7.3" @@ -48,7 +48,7 @@ ksp = "com.google.devtools.ksp:1.8.22-1.0.11" kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } -spotless = "com.diffplug.spotless:6.14.0" +spotless = "com.diffplug.spotless:6.21.0" detekt = "io.gitlab.arturbosch.detekt:1.23.0" dependency-check = "com.github.ben-manes.versions:0.46.0" diff --git a/mail/common/src/main/java/com/fsck/k9/mail/internet/MimeHeaderEncoder.kt b/mail/common/src/main/java/com/fsck/k9/mail/internet/MimeHeaderEncoder.kt index 6080afbbce..9654381e40 100644 --- a/mail/common/src/main/java/com/fsck/k9/mail/internet/MimeHeaderEncoder.kt +++ b/mail/common/src/main/java/com/fsck/k9/mail/internet/MimeHeaderEncoder.kt @@ -17,10 +17,12 @@ object MimeHeaderEncoder { } private fun exceedsRecommendedLineLength(name: String, value: String): Boolean { - return name.length + 2 /* colon + space */ + value.length > RECOMMENDED_MAX_LINE_LENGTH + return name.length + COLON_PLUS_SPACE_LENGTH + value.length > RECOMMENDED_MAX_LINE_LENGTH } private fun charactersNeedEncoding(text: String): Boolean { return text.any { !it.isVChar() && !it.isWspOrCrlf() } } + + private const val COLON_PLUS_SPACE_LENGTH = 2 } diff --git a/mail/common/src/main/java/com/fsck/k9/mail/internet/MimeParameterEncoder.kt b/mail/common/src/main/java/com/fsck/k9/mail/internet/MimeParameterEncoder.kt index fe6b861a4a..82a4b40929 100644 --- a/mail/common/src/main/java/com/fsck/k9/mail/internet/MimeParameterEncoder.kt +++ b/mail/common/src/main/java/com/fsck/k9/mail/internet/MimeParameterEncoder.kt @@ -13,6 +13,12 @@ object MimeParameterEncoder { private const val ENCODED_VALUE_PREFIX = "UTF-8''" + private const val FOLDING_SPACE_LENGTH = 1 + private const val EQUAL_SIGN_LENGTH = 1 + private const val SEMICOLON_LENGTH = 1 + private const val QUOTES_LENGTH = 2 + private const val ASTERISK_LENGTH = 1 + /** * Create header field value with parameters encoded if necessary. */ @@ -35,9 +41,9 @@ object MimeParameterEncoder { } private fun StringBuilder.encodeAndAppendParameter(name: String, value: String) { - val fixedCostLength = 1 /* folding space */ + name.length + 1 /* equals sign */ + 1 /* semicolon */ + val fixedCostLength = FOLDING_SPACE_LENGTH + name.length + EQUAL_SIGN_LENGTH + SEMICOLON_LENGTH val unencodedValueFitsOnSingleLine = fixedCostLength + value.length <= MAX_LINE_LENGTH - val quotedValueMightFitOnSingleLine = fixedCostLength + value.length + 2 /* quotes */ <= MAX_LINE_LENGTH + val quotedValueMightFitOnSingleLine = fixedCostLength + value.length + QUOTES_LENGTH <= MAX_LINE_LENGTH if (unencodedValueFitsOnSingleLine && value.isToken()) { appendParameter(name, value) @@ -56,8 +62,8 @@ object MimeParameterEncoder { } private fun StringBuilder.rfc2231EncodeAndAppendParameter(name: String, value: String) { - val encodedValueLength = 1 /* folding space */ + name.length + 1 /* asterisk */ + 1 /* equal sign */ + - ENCODED_VALUE_PREFIX.length + value.rfc2231EncodedLength() + 1 /* semicolon */ + val encodedValueLength = FOLDING_SPACE_LENGTH + name.length + ASTERISK_LENGTH + EQUAL_SIGN_LENGTH + + ENCODED_VALUE_PREFIX.length + value.rfc2231EncodedLength() + SEMICOLON_LENGTH if (encodedValueLength <= MAX_LINE_LENGTH) { appendRfc2231SingleLineParameter(name, value.rfc2231Encoded()) @@ -88,7 +94,7 @@ object MimeParameterEncoder { append(ENCODED_VALUE_PREFIX) } - remainingSpaceInLine = MAX_LINE_LENGTH - (length - lineStartIndex) - 1 /* semicolon */ + remainingSpaceInLine = MAX_LINE_LENGTH - (length - lineStartIndex) - SEMICOLON_LENGTH if (remainingSpaceInLine < 3) { throw UnsupportedOperationException("Parameter name too long") } @@ -182,7 +188,7 @@ object MimeParameterEncoder { } private fun String.quotedLength(): Int { - var length = 2 /* start and end quote */ + var length = QUOTES_LENGTH for (c in this) { if (c.isQText() || c.isWsp()) { length++ diff --git a/mail/common/src/test/java/com/fsck/k9/mail/internet/MimeHeaderCheckerTest.kt b/mail/common/src/test/java/com/fsck/k9/mail/internet/MimeHeaderCheckerTest.kt index 9c5ed4543b..b53d12d2a6 100644 --- a/mail/common/src/test/java/com/fsck/k9/mail/internet/MimeHeaderCheckerTest.kt +++ b/mail/common/src/test/java/com/fsck/k9/mail/internet/MimeHeaderCheckerTest.kt @@ -58,25 +58,27 @@ class MimeHeaderCheckerTest { @Test fun singleLineAtMaximumLineLength() { - val longText = "x".repeat(998 /* text limit */ - 4 /* Test */ - 2 /* colon, space */) + val test = 4 + val longText = "x".repeat(MAXIMUM_LINE_LENGTH - test - COLON_PLUS_SPACE_LENGTH) assertValidHeader("Test: $longText") } @Test fun firstLineAtMaximumLineLength() { - val longText = "x".repeat(998 /* text limit */ - 4 /* Test */ - 2 /* colon, space */) + val test = 4 + val longText = "x".repeat(MAXIMUM_LINE_LENGTH - test - COLON_PLUS_SPACE_LENGTH) assertValidHeader("Test: $longText\r\n Text") } @Test fun middleLineAtMaximumLineLength() { - val longText = "x".repeat(998 - 1 /* space */) + val longText = "x".repeat(MAXIMUM_LINE_LENGTH - SPACE_LENGTH) assertValidHeader("Test: One\r\n $longText\r\n Three") } @Test fun lastLineAtMaximumLineLength() { - val longText = "x".repeat(998 - 1 /* space */) + val longText = "x".repeat(MAXIMUM_LINE_LENGTH - SPACE_LENGTH) assertValidHeader("Test: One\r\n $longText") } @@ -92,7 +94,7 @@ class MimeHeaderCheckerTest { @Test fun headerNameExceedingLineLimit() { - val longName = "x".repeat(998 - 2 /* space, colon */ + 1) + val longName = "x".repeat(MAXIMUM_LINE_LENGTH - COLON_PLUS_SPACE_LENGTH + 1) assertInvalidHeader("$longName: ") } @@ -173,25 +175,28 @@ class MimeHeaderCheckerTest { @Test fun singleLineExceedingLineLength() { - val longText = "x".repeat(998 /* text limit */ - 4 /* Test */ - 2 /* colon, space */ + 1) + val test = 4 + + val longText = "x".repeat(MAXIMUM_LINE_LENGTH - test - COLON_PLUS_SPACE_LENGTH + 1) assertInvalidHeader("Test: $longText") } @Test fun firstLineExceedingLineLength() { - val longText = "x".repeat(998 /* text limit */ - 4 /* Test */ - 2 /* colon, space */ + 1) + val test = 4 + val longText = "x".repeat(MAXIMUM_LINE_LENGTH - test - COLON_PLUS_SPACE_LENGTH + 1) assertInvalidHeader("Test: $longText\r\n Text") } @Test fun middleLineExceedingLineLength() { - val longText = "x".repeat(998 - 1 /* space */ + 1) + val longText = "x".repeat(MAXIMUM_LINE_LENGTH - SPACE_LENGTH + 1) assertInvalidHeader("Test: One\r\n $longText\r\n Three") } @Test fun lastLineExceedingLineLength() { - val longText = "x".repeat(998 - 1 /* space */ + 1) + val longText = "x".repeat(MAXIMUM_LINE_LENGTH - SPACE_LENGTH + 1) assertInvalidHeader("Test: One\r\n $longText") } @@ -208,4 +213,10 @@ class MimeHeaderCheckerTest { MimeHeaderChecker.checkHeader(name, value) }.isInstanceOf() } + + private companion object { + private const val MAXIMUM_LINE_LENGTH = 998 + private const val COLON_PLUS_SPACE_LENGTH = 2 + private const val SPACE_LENGTH = 1 + } } diff --git a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/RealImapFolder.kt b/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/RealImapFolder.kt index 26ff4103d4..a80d0ec3fe 100644 --- a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/RealImapFolder.kt +++ b/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/RealImapFolder.kt @@ -100,7 +100,8 @@ internal class RealImapFolder( try { return executeSimpleCommand(Commands.NOOP) } catch (ioe: IOException) { - /* don't throw */ ioExceptionHandler(connection, ioe) + /* don't throw */ + ioExceptionHandler(connection, ioe) } } -- GitLab From 49bde4fab75b460f8a5c9428db65c43aecc13516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 12:50:59 +0200 Subject: [PATCH 27/94] Remove needles initial state loading as it is covered by the LoadAccountState event --- .../AccountIncomingConfigViewModel.kt | 7 +-- .../AccountOutgoingConfigViewModel.kt | 7 +-- .../AccountIncomingConfigViewModelTest.kt | 43 +------------------ .../AccountOutgoingConfigViewModelTest.kt | 42 +----------------- 4 files changed, 6 insertions(+), 93 deletions(-) diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModel.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModel.kt index 4ea05db564..510425e59c 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModel.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModel.kt @@ -15,11 +15,8 @@ import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfi class AccountIncomingConfigViewModel( private val validator: Validator, private val accountStateRepository: AccountDomainContract.AccountStateRepository, - initialState: State? = null, -) : BaseViewModel( - initialState = initialState ?: accountStateRepository.getState().toIncomingConfigState(), -), - ViewModel { + initialState: State = State(), +) : BaseViewModel(initialState = initialState), ViewModel { @Suppress("CyclomaticComplexMethod") override fun event(event: Event) { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModel.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModel.kt index b706474c01..50a96a14ef 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModel.kt +++ b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModel.kt @@ -14,11 +14,8 @@ import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfi class AccountOutgoingConfigViewModel( private val validator: Validator, private val accountStateRepository: AccountDomainContract.AccountStateRepository, - initialState: State? = State(), -) : BaseViewModel( - initialState = initialState ?: accountStateRepository.getState().toOutgoingConfigState(), -), - ViewModel { + initialState: State = State(), +) : BaseViewModel(initialState = initialState), ViewModel { override fun event(event: Event) { when (event) { diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModelTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModelTest.kt index 74ec973172..7736113233 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModelTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModelTest.kt @@ -35,46 +35,6 @@ class AccountIncomingConfigViewModelTest { @get:Rule val mainDispatcherRule = MainDispatcherRule() - @Test - fun `should take initial state from repository when no initial state is provided`() = runTest { - val accountState = AccountState( - emailAddress = "test@example.com", - incomingServerSettings = ServerSettings( - "imap", - "imap.example.com", - 123, - MailConnectionSecurity.SSL_TLS_REQUIRED, - AuthType.PLAIN, - "username", - "password", - clientCertificateAlias = null, - extra = emptyMap(), - ), - ) - val testSubject = createTestSubject( - initialState = null, - repository = InMemoryAccountStateRepository(accountState), - ) - val turbines = turbines(testSubject) - - assertThatAndMviTurbinesConsumed( - actual = turbines.awaitStateItem(), - turbines = turbines, - ) { - isEqualTo( - State( - protocolType = IncomingProtocolType.IMAP, - server = StringInputField(value = "imap.example.com"), - security = ConnectionSecurity.TLS, - port = NumberInputField(value = 123L), - authenticationType = AuthenticationType.PasswordCleartext, - username = StringInputField(value = "username"), - password = StringInputField(value = "password"), - ), - ) - } - } - @Test fun `should load account setup state when LoadAccountState event is received`() = runTest { val accountState = AccountState( @@ -93,7 +53,6 @@ class AccountIncomingConfigViewModelTest { ) val repository = InMemoryAccountStateRepository(AccountState()) val testSubject = createTestSubject( - initialState = null, repository = repository, ) val turbines = turbinesWithInitialStateCheck(testSubject, State()) @@ -434,7 +393,7 @@ class AccountIncomingConfigViewModelTest { private companion object { fun createTestSubject( - initialState: State? = null, + initialState: State = State(), validator: AccountIncomingConfigContract.Validator = FakeAccountIncomingConfigValidator(), repository: AccountDomainContract.AccountStateRepository = InMemoryAccountStateRepository(), ) = AccountIncomingConfigViewModel( diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModelTest.kt b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModelTest.kt index 4a38c3c311..92ad3ef3a8 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModelTest.kt +++ b/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModelTest.kt @@ -33,45 +33,6 @@ class AccountOutgoingConfigViewModelTest { @get:Rule val mainDispatcherRule = MainDispatcherRule() - @Test - fun `should take initial state from repository when no initial state is provided`() = runTest { - val accountState = AccountState( - emailAddress = "test@example.com", - outgoingServerSettings = ServerSettings( - "smtp", - "smtp.example.com", - 123, - MailConnectionSecurity.SSL_TLS_REQUIRED, - AuthType.PLAIN, - "username", - "password", - clientCertificateAlias = null, - extra = emptyMap(), - ), - ) - val testSubject = createTestSubject( - initialState = null, - repository = InMemoryAccountStateRepository(accountState), - ) - val turbines = turbines(testSubject) - - assertThatAndMviTurbinesConsumed( - actual = turbines.awaitStateItem(), - turbines = turbines, - ) { - isEqualTo( - State( - server = StringInputField(value = "smtp.example.com"), - security = ConnectionSecurity.TLS, - port = NumberInputField(value = 123L), - authenticationType = AuthenticationType.PasswordCleartext, - username = StringInputField(value = "username"), - password = StringInputField(value = "password"), - ), - ) - } - } - @Test fun `should load account setup state when LoadAccountState event is received`() = runTest { val accountState = AccountState( @@ -90,7 +51,6 @@ class AccountOutgoingConfigViewModelTest { ) val repository = InMemoryAccountStateRepository(AccountState()) val testSubject = createTestSubject( - initialState = null, repository = repository, ) val turbines = turbinesWithInitialStateCheck(testSubject, State()) @@ -340,7 +300,7 @@ class AccountOutgoingConfigViewModelTest { private companion object { fun createTestSubject( - initialState: State? = null, + initialState: State = State(), validator: AccountOutgoingConfigContract.Validator = FakeAccountOutgoingConfigValidator(), repository: AccountDomainContract.AccountStateRepository = InMemoryAccountStateRepository(), ) = AccountOutgoingConfigViewModel( -- GitLab From 009f235fe785b4a089340a5032b5bc536cf7bdd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 13:07:56 +0200 Subject: [PATCH 28/94] Rename module from config to settings for consistency --- .../mapper/AuthenticationTypeStringMapper.kt | 29 -------------- .../mapper/ConnectionSecurityStringMapper.kt | 13 ------ .../FakeAccountIncomingConfigViewModel.kt | 22 ---------- .../FakeAccountOutgoingConfigViewModel.kt | 22 ---------- .../config/src/main/res/values/strings.xml | 40 ------------------- .../{config => settings}/build.gradle.kts | 4 +- .../server/settings}/ServerConfigModule.kt | 14 +++---- .../domain/ServerConfigDomainContract.kt | 2 +- .../domain/usecase/ValidateEmailAddress.kt | 4 +- .../domain/usecase/ValidateImapPrefix.kt | 4 +- .../domain/usecase/ValidatePassword.kt | 4 +- .../settings}/domain/usecase/ValidatePort.kt | 4 +- .../domain/usecase/ValidateServer.kt | 4 +- .../domain/usecase/ValidateUsername.kt | 4 +- .../ui/common/ClientCertificateInput.kt | 6 +-- .../mapper/AuthenticationTypeStringMapper.kt | 29 ++++++++++++++ .../mapper/ConnectionSecurityStringMapper.kt | 15 +++++++ .../mapper/ValidationErrorStringMapper.kt | 32 +++++++-------- .../incoming/AccountIncomingConfigContent.kt | 36 ++++++++--------- .../incoming/AccountIncomingConfigContract.kt | 2 +- .../incoming/AccountIncomingConfigScreen.kt | 12 +++--- .../AccountIncomingConfigStateExtensions.kt | 2 +- .../AccountIncomingConfigStateMapper.kt | 4 +- .../AccountIncomingConfigValidator.kt | 14 +++---- .../AccountIncomingConfigViewModel.kt | 13 +++--- .../FakeAccountIncomingConfigValidator.kt | 4 +- .../FakeAccountIncomingConfigViewModel.kt | 22 ++++++++++ .../outgoing/AccountOutgoingConfigContent.kt | 24 +++++------ .../outgoing/AccountOutgoingConfigContract.kt | 2 +- .../outgoing/AccountOutgoingConfigScreen.kt | 12 +++--- .../AccountOutgoingConfigStateExtensions.kt | 2 +- .../AccountOutgoingConfigStateMapper.kt | 4 +- .../AccountOutgoingConfigValidator.kt | 10 ++--- .../AccountOutgoingConfigViewModel.kt | 12 +++--- .../FakeAccountOutgoingConfigValidator.kt | 4 +- .../FakeAccountOutgoingConfigViewModel.kt | 22 ++++++++++ .../settings/src/main/res/values/strings.xml | 40 +++++++++++++++++++ .../usecase/ValidateEmailAddressTest.kt | 4 +- .../domain/usecase/ValidateImapPrefixTest.kt | 2 +- .../domain/usecase/ValidatePasswordTest.kt | 2 +- .../domain/usecase/ValidatePortTest.kt | 4 +- .../domain/usecase/ValidateServerTest.kt | 2 +- .../domain/usecase/ValidateUsernameTest.kt | 2 +- .../AccountIncomingConfigScreenKtTest.kt | 8 ++-- .../AccountIncomingConfigStateMapperKtTest.kt | 4 +- .../AccountIncomingConfigStateTest.kt | 4 +- .../AccountIncomingConfigViewModelTest.kt | 10 ++--- .../AccountOutgoingConfigScreenKtTest.kt | 8 ++-- .../AccountOutgoingConfigStateMapperKtTest.kt | 4 +- .../AccountOutgoingConfigStateTest.kt | 4 +- .../AccountOutgoingConfigViewModelTest.kt | 10 ++--- feature/account/setup/build.gradle.kts | 2 +- .../account/setup/AccountSetupModule.kt | 2 +- .../account/setup/ui/AccountSetupScreen.kt | 12 +++--- .../AccountAutoDiscoveryStateMapper.kt | 4 +- .../AccountAutoDiscoveryValidator.kt | 6 +-- .../ui/autodiscovery/item/EmailAddressItem.kt | 2 +- .../ui/autodiscovery/item/PasswordItem.kt | 2 +- .../account/setup/AccountSetupModuleKtTest.kt | 4 +- .../setup/ui/AccountSetupScreenKtTest.kt | 4 +- .../AccountAutoDiscoveryStateMapperKtTest.kt | 4 +- settings.gradle.kts | 2 +- 62 files changed, 304 insertions(+), 301 deletions(-) delete mode 100644 feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/AuthenticationTypeStringMapper.kt delete mode 100644 feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ConnectionSecurityStringMapper.kt delete mode 100644 feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt delete mode 100644 feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt delete mode 100644 feature/account/server/config/src/main/res/values/strings.xml rename feature/account/server/{config => settings}/build.gradle.kts (86%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ServerConfigModule.kt (51%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/domain/ServerConfigDomainContract.kt (93%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidateEmailAddress.kt (86%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidateImapPrefix.kt (80%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidatePassword.kt (80%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidatePort.kt (83%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidateServer.kt (79%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidateUsername.kt (78%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/common/ClientCertificateInput.kt (89%) create mode 100644 feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/AuthenticationTypeStringMapper.kt create mode 100644 feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ConnectionSecurityStringMapper.kt rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/common/mapper/ValidationErrorStringMapper.kt (59%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigContent.kt (89%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigContract.kt (98%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigScreen.kt (85%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigStateExtensions.kt (95%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigStateMapper.kt (94%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigValidator.kt (68%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigViewModel.kt (88%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt (85%) create mode 100644 feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigContent.kt (89%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigContract.kt (97%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigScreen.kt (85%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigStateExtensions.kt (80%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigStateMapper.kt (92%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigValidator.kt (70%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigViewModel.kt (85%) rename feature/account/server/{config/src/main/kotlin/app/k9mail/feature/account/server/config => settings/src/main/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt (83%) create mode 100644 feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt create mode 100644 feature/account/server/settings/src/main/res/values/strings.xml rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidateEmailAddressTest.kt (86%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidateImapPrefixTest.kt (93%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidatePasswordTest.kt (94%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidatePortTest.kt (90%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidateServerTest.kt (94%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/domain/usecase/ValidateUsernameTest.kt (94%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigScreenKtTest.kt (75%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt (95%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigStateTest.kt (89%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/ui/incoming/AccountIncomingConfigViewModelTest.kt (97%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt (75%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt (90%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigStateTest.kt (86%) rename feature/account/server/{config/src/test/kotlin/app/k9mail/feature/account/server/config => settings/src/test/kotlin/app/k9mail/feature/account/server/settings}/ui/outgoing/AccountOutgoingConfigViewModelTest.kt (96%) diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/AuthenticationTypeStringMapper.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/AuthenticationTypeStringMapper.kt deleted file mode 100644 index 59d1b221e2..0000000000 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/AuthenticationTypeStringMapper.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.k9mail.feature.account.server.config.ui.common.mapper - -import android.content.res.Resources -import app.k9mail.feature.account.common.domain.entity.AuthenticationType -import app.k9mail.feature.account.server.config.R - -internal fun AuthenticationType.toResourceString(resources: Resources): String { - return when (this) { - AuthenticationType.None -> { - resources.getString(R.string.account_server_config_authentication_none) - } - - AuthenticationType.PasswordCleartext -> { - resources.getString(R.string.account_server_config_authentication_password_cleartext) - } - - AuthenticationType.PasswordEncrypted -> { - resources.getString(R.string.account_server_config_authentication_password_encrypted) - } - - AuthenticationType.ClientCertificate -> { - resources.getString(R.string.account_server_config_authentication_client_certificate) - } - - AuthenticationType.OAuth2 -> { - resources.getString(R.string.account_server_config_authentication_client_oauth) - } - } -} diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ConnectionSecurityStringMapper.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ConnectionSecurityStringMapper.kt deleted file mode 100644 index d232a961a9..0000000000 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ConnectionSecurityStringMapper.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.k9mail.feature.account.server.config.ui.common.mapper - -import android.content.res.Resources -import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity -import app.k9mail.feature.account.server.config.R - -internal fun ConnectionSecurity.toResourceString(resources: Resources): String { - return when (this) { - ConnectionSecurity.None -> resources.getString(R.string.account_server_config_connection_security_none) - ConnectionSecurity.StartTLS -> resources.getString(R.string.account_server_config_connection_security_start_tls) - ConnectionSecurity.TLS -> resources.getString(R.string.account_server_config_connection_security_ssl) - } -} diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt deleted file mode 100644 index 6613f9abdd..0000000000 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.k9mail.feature.account.server.config.ui.incoming.fake - -import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.ViewModel - -class FakeAccountIncomingConfigViewModel( - initialState: State = State(), -) : BaseViewModel(initialState), ViewModel { - - val events = mutableListOf() - - override fun event(event: Event) { - events.add(event) - } - - fun effect(effect: Effect) { - emitEffect(effect) - } -} diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt b/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt deleted file mode 100644 index 5830438542..0000000000 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.k9mail.feature.account.server.config.ui.outgoing.fake - -import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.ViewModel - -class FakeAccountOutgoingConfigViewModel( - initialState: State = State(), -) : BaseViewModel(initialState), ViewModel { - - val events = mutableListOf() - - override fun event(event: Event) { - events.add(event) - } - - fun effect(effect: Effect) { - emitEffect(effect) - } -} diff --git a/feature/account/server/config/src/main/res/values/strings.xml b/feature/account/server/config/src/main/res/values/strings.xml deleted file mode 100644 index a32a430c65..0000000000 --- a/feature/account/server/config/src/main/res/values/strings.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - Protocol - Server - Security - Port - Authentication - Username - - None - StartTLS - SSL/TLS - - None - Normal password - Encrypted password - Client certificate - OAuth 2.0 - - None - Client certificate - - Incoming server settings - - Auto-detect IMAP namespace - IMAP path prefix - Use compression - Send client ID - - Outgoing server settings - - Email address is required. - Email address is invalid. - Server name is required. - Port is required. - Port is invalid (must be 1–65535). - Username is required. - Password is required. - Imap prefix can\'t be blank. - diff --git a/feature/account/server/config/build.gradle.kts b/feature/account/server/settings/build.gradle.kts similarity index 86% rename from feature/account/server/config/build.gradle.kts rename to feature/account/server/settings/build.gradle.kts index 1adbc030a0..5e9c127b18 100644 --- a/feature/account/server/config/build.gradle.kts +++ b/feature/account/server/settings/build.gradle.kts @@ -3,8 +3,8 @@ plugins { } android { - namespace = "app.k9mail.feature.account.server.config" - resourcePrefix = "account_server_config_" + namespace = "app.k9mail.feature.account.server.settings" + resourcePrefix = "account_server_settings_" buildTypes { debug { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ServerConfigModule.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt similarity index 51% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ServerConfigModule.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt index 5b3ed5345b..638e4b0101 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ServerConfigModule.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt @@ -1,11 +1,11 @@ -package app.k9mail.feature.account.server.config +package app.k9mail.feature.account.server.settings -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigValidator -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigViewModel -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigValidator -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigValidator +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigValidator +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigViewModel import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.core.module.Module import org.koin.dsl.module diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/ServerConfigDomainContract.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerConfigDomainContract.kt similarity index 93% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/ServerConfigDomainContract.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerConfigDomainContract.kt index ce9dc8bfb9..6a1b0cf526 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/ServerConfigDomainContract.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerConfigDomainContract.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.domain +package app.k9mail.feature.account.server.settings.domain import app.k9mail.core.common.domain.usecase.validation.ValidationResult diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddress.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddress.kt similarity index 86% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddress.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddress.kt index c33f224e1c..0548e11c05 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddress.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddress.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase class ValidateEmailAddress : UseCase.ValidateEmailAddress { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefix.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateImapPrefix.kt similarity index 80% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefix.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateImapPrefix.kt index 43845b0894..d180d61a59 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefix.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateImapPrefix.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase internal class ValidateImapPrefix : UseCase.ValidateImapPrefix { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePassword.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePassword.kt similarity index 80% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePassword.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePassword.kt index b0a95b4c82..00389b1853 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePassword.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePassword.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase class ValidatePassword : UseCase.ValidatePassword { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePort.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePort.kt similarity index 83% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePort.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePort.kt index 30288f24c6..e27e3c7fb8 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePort.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePort.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase internal class ValidatePort : UseCase.ValidatePort { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServer.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateServer.kt similarity index 79% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServer.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateServer.kt index 7fbe43c7a4..c264c4e4f6 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServer.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateServer.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase internal class ValidateServer : UseCase.ValidateServer { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsername.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateUsername.kt similarity index 78% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsername.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateUsername.kt index c83482cbd2..647e80064c 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsername.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateUsername.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase internal class ValidateUsername : UseCase.ValidateUsername { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/ClientCertificateInput.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/ClientCertificateInput.kt similarity index 89% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/ClientCertificateInput.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/ClientCertificateInput.kt index 9cbbd3b8c6..b35095fc7a 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/ClientCertificateInput.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/ClientCertificateInput.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.common +package app.k9mail.feature.account.server.settings.ui.common import android.security.KeyChain import androidx.compose.foundation.layout.Column @@ -11,7 +11,7 @@ import androidx.compose.ui.res.stringResource import app.k9mail.core.ui.compose.common.activity.LocalActivity import app.k9mail.core.ui.compose.designsystem.atom.textfield.TextFieldOutlinedFakeSelect import app.k9mail.core.ui.compose.designsystem.molecule.input.inputContentPadding -import app.k9mail.feature.account.server.config.R +import app.k9mail.feature.account.server.settings.R @Composable fun ClientCertificateInput( @@ -29,7 +29,7 @@ fun ClientCertificateInput( ) { val activity = LocalActivity.current TextFieldOutlinedFakeSelect( - text = alias ?: stringResource(R.string.account_server_config_client_certificate_none_selected), + text = alias ?: stringResource(R.string.account_server_settings_client_certificate_none_selected), onClick = { KeyChain.choosePrivateKeyAlias(activity, onValueChange, null, null, null, -1, alias) }, diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/AuthenticationTypeStringMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/AuthenticationTypeStringMapper.kt new file mode 100644 index 0000000000..a66246c622 --- /dev/null +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/AuthenticationTypeStringMapper.kt @@ -0,0 +1,29 @@ +package app.k9mail.feature.account.server.settings.ui.common.mapper + +import android.content.res.Resources +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.server.settings.R + +internal fun AuthenticationType.toResourceString(resources: Resources): String { + return when (this) { + AuthenticationType.None -> { + resources.getString(R.string.account_server_settings_authentication_none) + } + + AuthenticationType.PasswordCleartext -> { + resources.getString(R.string.account_server_settings_authentication_password_cleartext) + } + + AuthenticationType.PasswordEncrypted -> { + resources.getString(R.string.account_server_settings_authentication_password_encrypted) + } + + AuthenticationType.ClientCertificate -> { + resources.getString(R.string.account_server_settings_authentication_client_certificate) + } + + AuthenticationType.OAuth2 -> { + resources.getString(R.string.account_server_settings_authentication_client_oauth) + } + } +} diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ConnectionSecurityStringMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ConnectionSecurityStringMapper.kt new file mode 100644 index 0000000000..7d27104f20 --- /dev/null +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ConnectionSecurityStringMapper.kt @@ -0,0 +1,15 @@ +package app.k9mail.feature.account.server.settings.ui.common.mapper + +import android.content.res.Resources +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.server.settings.R + +internal fun ConnectionSecurity.toResourceString(resources: Resources): String { + return when (this) { + ConnectionSecurity.None -> resources.getString(R.string.account_server_settings_connection_security_none) + ConnectionSecurity.StartTLS -> resources.getString( + R.string.account_server_settings_connection_security_start_tls, + ) + ConnectionSecurity.TLS -> resources.getString(R.string.account_server_settings_connection_security_ssl) + } +} diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ValidationErrorStringMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ValidationErrorStringMapper.kt similarity index 59% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ValidationErrorStringMapper.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ValidationErrorStringMapper.kt index 949dee84da..40a4f0f418 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/common/mapper/ValidationErrorStringMapper.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ValidationErrorStringMapper.kt @@ -1,14 +1,14 @@ -package app.k9mail.feature.account.server.config.ui.common.mapper +package app.k9mail.feature.account.server.settings.ui.common.mapper import android.content.res.Resources import app.k9mail.core.common.domain.usecase.validation.ValidationError -import app.k9mail.feature.account.server.config.R -import app.k9mail.feature.account.server.config.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError -import app.k9mail.feature.account.server.config.domain.usecase.ValidateImapPrefix.ValidateImapPrefixError -import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword.ValidatePasswordError -import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort.ValidatePortError -import app.k9mail.feature.account.server.config.domain.usecase.ValidateServer.ValidateServerError -import app.k9mail.feature.account.server.config.domain.usecase.ValidateUsername.ValidateUsernameError +import app.k9mail.feature.account.server.settings.R +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateImapPrefix.ValidateImapPrefixError +import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePassword.ValidatePasswordError +import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePort.ValidatePortError +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateServer.ValidateServerError +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateUsername.ValidateUsernameError fun ValidationError.toResourceString(resources: Resources): String { return when (this) { @@ -25,11 +25,11 @@ fun ValidationError.toResourceString(resources: Resources): String { private fun ValidateEmailAddressError.toEmailAddressErrorString(resources: Resources): String { return when (this) { is ValidateEmailAddressError.EmptyEmailAddress -> resources.getString( - R.string.account_server_config_validation_error_email_address_required, + R.string.account_server_settings_validation_error_email_address_required, ) is ValidateEmailAddressError.InvalidEmailAddress -> resources.getString( - R.string.account_server_config_validation_error_email_address_invalid, + R.string.account_server_settings_validation_error_email_address_invalid, ) } } @@ -37,7 +37,7 @@ private fun ValidateEmailAddressError.toEmailAddressErrorString(resources: Resou private fun ValidateServerError.toServerErrorString(resources: Resources): String { return when (this) { is ValidateServerError.EmptyServer -> resources.getString( - R.string.account_server_config_validation_error_server_required, + R.string.account_server_settings_validation_error_server_required, ) } } @@ -45,11 +45,11 @@ private fun ValidateServerError.toServerErrorString(resources: Resources): Strin private fun ValidatePortError.toPortErrorString(resources: Resources): String { return when (this) { is ValidatePortError.EmptyPort -> resources.getString( - R.string.account_server_config_validation_error_port_required, + R.string.account_server_settings_validation_error_port_required, ) is ValidatePortError.InvalidPort -> resources.getString( - R.string.account_server_config_validation_error_port_invalid, + R.string.account_server_settings_validation_error_port_invalid, ) } } @@ -57,7 +57,7 @@ private fun ValidatePortError.toPortErrorString(resources: Resources): String { private fun ValidateUsernameError.toUsernameErrorString(resources: Resources): String { return when (this) { ValidateUsernameError.EmptyUsername -> resources.getString( - R.string.account_server_config_validation_error_username_required, + R.string.account_server_settings_validation_error_username_required, ) } } @@ -65,7 +65,7 @@ private fun ValidateUsernameError.toUsernameErrorString(resources: Resources): S private fun ValidatePasswordError.toPasswordErrorString(resources: Resources): String { return when (this) { ValidatePasswordError.EmptyPassword -> resources.getString( - R.string.account_server_config_validation_error_password_required, + R.string.account_server_settings_validation_error_password_required, ) } } @@ -73,7 +73,7 @@ private fun ValidatePasswordError.toPasswordErrorString(resources: Resources): S private fun ValidateImapPrefixError.toImapPrefixErrorString(resources: Resources): String { return when (this) { ValidateImapPrefixError.BlankImapPrefix -> resources.getString( - R.string.account_server_config_validation_error_imap_prefix_blank, + R.string.account_server_settings_validation_error_imap_prefix_blank, ) } } diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContent.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContent.kt similarity index 89% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContent.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContent.kt index 83aec7853d..247fbe5d90 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContent.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContent.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues @@ -28,11 +28,11 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.ui.item.defaultItemPadding -import app.k9mail.feature.account.server.config.R -import app.k9mail.feature.account.server.config.ui.common.ClientCertificateInput -import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.R +import app.k9mail.feature.account.server.settings.ui.common.ClientCertificateInput +import app.k9mail.feature.account.server.settings.ui.common.mapper.toResourceString +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State @Suppress("LongMethod") @Composable @@ -67,7 +67,7 @@ internal fun AccountIncomingConfigContent( options = IncomingProtocolType.all(), selectedOption = state.protocolType, onOptionChange = { onEvent(Event.ProtocolTypeChanged(it)) }, - label = stringResource(id = R.string.account_server_config_protocol_type_label), + label = stringResource(id = R.string.account_server_settings_protocol_type_label), contentPadding = defaultItemPadding(), ) } @@ -77,7 +77,7 @@ internal fun AccountIncomingConfigContent( text = state.server.value, errorMessage = state.server.error?.toResourceString(resources), onTextChange = { onEvent(Event.ServerChanged(it)) }, - label = stringResource(id = R.string.account_server_config_server_label), + label = stringResource(id = R.string.account_server_settings_server_label), contentPadding = defaultItemPadding(), ) } @@ -88,7 +88,7 @@ internal fun AccountIncomingConfigContent( optionToStringTransformation = { it.toResourceString(resources) }, selectedOption = state.security, onOptionChange = { onEvent(Event.SecurityChanged(it)) }, - label = stringResource(id = R.string.account_server_config_security_label), + label = stringResource(id = R.string.account_server_settings_security_label), contentPadding = defaultItemPadding(), ) } @@ -98,7 +98,7 @@ internal fun AccountIncomingConfigContent( value = state.port.value, errorMessage = state.port.error?.toResourceString(resources), onValueChange = { onEvent(Event.PortChanged(it)) }, - label = stringResource(id = R.string.account_server_config_port_label), + label = stringResource(id = R.string.account_server_settings_port_label), contentPadding = defaultItemPadding(), ) } @@ -109,7 +109,7 @@ internal fun AccountIncomingConfigContent( optionToStringTransformation = { it.toResourceString(resources) }, selectedOption = state.authenticationType, onOptionChange = { onEvent(Event.AuthenticationTypeChanged(it)) }, - label = stringResource(id = R.string.account_server_config_authentication_label), + label = stringResource(id = R.string.account_server_settings_authentication_label), contentPadding = defaultItemPadding(), ) } @@ -119,7 +119,7 @@ internal fun AccountIncomingConfigContent( text = state.username.value, errorMessage = state.username.error?.toResourceString(resources), onTextChange = { onEvent(Event.UsernameChanged(it)) }, - label = stringResource(id = R.string.account_server_config_username_label), + label = stringResource(id = R.string.account_server_settings_username_label), contentPadding = defaultItemPadding(), ) } @@ -139,7 +139,7 @@ internal fun AccountIncomingConfigContent( ClientCertificateInput( alias = state.clientCertificateAlias, onValueChange = { onEvent(Event.ClientCertificateChanged(it)) }, - label = stringResource(id = R.string.account_server_config_client_certificate_label), + label = stringResource(id = R.string.account_server_settings_client_certificate_label), contentPadding = defaultItemPadding(), ) } @@ -147,7 +147,7 @@ internal fun AccountIncomingConfigContent( if (state.protocolType == IncomingProtocolType.IMAP) { item { CheckboxInput( - text = stringResource(id = R.string.account_server_config_incoming_imap_namespace_label), + text = stringResource(id = R.string.account_server_settings_incoming_imap_namespace_label), checked = state.imapAutodetectNamespaceEnabled, onCheckedChange = { onEvent(Event.ImapAutoDetectNamespaceChanged(it)) }, contentPadding = defaultItemPadding(), @@ -158,7 +158,7 @@ internal fun AccountIncomingConfigContent( if (state.imapAutodetectNamespaceEnabled) { TextInput( onTextChange = {}, - label = stringResource(id = R.string.account_server_config_incoming_imap_prefix_label), + label = stringResource(id = R.string.account_server_settings_incoming_imap_prefix_label), contentPadding = defaultItemPadding(), isEnabled = false, ) @@ -167,7 +167,7 @@ internal fun AccountIncomingConfigContent( text = state.imapPrefix.value, errorMessage = state.imapPrefix.error?.toResourceString(resources), onTextChange = { onEvent(Event.ImapPrefixChanged(it)) }, - label = stringResource(id = R.string.account_server_config_incoming_imap_prefix_label), + label = stringResource(id = R.string.account_server_settings_incoming_imap_prefix_label), contentPadding = defaultItemPadding(), ) } @@ -175,7 +175,7 @@ internal fun AccountIncomingConfigContent( item { CheckboxInput( - text = stringResource(id = R.string.account_server_config_incoming_imap_compression_label), + text = stringResource(id = R.string.account_server_settings_incoming_imap_compression_label), checked = state.imapUseCompression, onCheckedChange = { onEvent(Event.ImapUseCompressionChanged(it)) }, contentPadding = defaultItemPadding(), @@ -184,7 +184,7 @@ internal fun AccountIncomingConfigContent( item { CheckboxInput( - text = stringResource(R.string.account_server_config_incoming_imap_send_client_id_label), + text = stringResource(R.string.account_server_settings_incoming_imap_send_client_id_label), checked = state.imapSendClientId, onCheckedChange = { onEvent(Event.ImapSendClientIdChanged(it)) }, contentPadding = defaultItemPadding(), diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContract.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContract.kt similarity index 98% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContract.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContract.kt index e361477ff1..4331a81209 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigContract.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContract.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreen.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreen.kt similarity index 85% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreen.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreen.kt index 56dc8a36c9..cbcd361f8f 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreen.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreen.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import androidx.activity.compose.BackHandler import androidx.compose.runtime.Composable @@ -13,10 +13,10 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.ui.AccountTopAppBar import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository -import app.k9mail.feature.account.server.config.R -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.ViewModel +import app.k9mail.feature.account.server.settings.R +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Effect +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.ViewModel @Composable fun AccountIncomingConfigScreen( @@ -43,7 +43,7 @@ fun AccountIncomingConfigScreen( Scaffold( topBar = { AccountTopAppBar( - title = stringResource(id = R.string.account_server_config_incoming_top_bar_title), + title = stringResource(id = R.string.account_server_settings_incoming_top_bar_title), ) }, bottomBar = { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateExtensions.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateExtensions.kt similarity index 95% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateExtensions.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateExtensions.kt index 5826868e40..3949c56a01 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateExtensions.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateExtensions.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapper.kt similarity index 94% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapper.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapper.kt index ed0e1bb96f..3f27078971 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapper.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapper.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType @@ -8,7 +8,7 @@ import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.store.imap.ImapStoreSettings diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigValidator.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigValidator.kt similarity index 68% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigValidator.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigValidator.kt index 4789900475..27a8e5a4ff 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigValidator.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigValidator.kt @@ -1,12 +1,12 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract.UseCase -import app.k9mail.feature.account.server.config.domain.usecase.ValidateImapPrefix -import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword -import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort -import app.k9mail.feature.account.server.config.domain.usecase.ValidateServer -import app.k9mail.feature.account.server.config.domain.usecase.ValidateUsername +import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateImapPrefix +import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePassword +import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePort +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateServer +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateUsername internal class AccountIncomingConfigValidator( private val serverValidator: UseCase.ValidateServer = ValidateServer(), diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModel.kt similarity index 88% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModel.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModel.kt index 510425e59c..fa4a1a7bdf 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModel.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModel.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel @@ -6,14 +6,15 @@ import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.toDefaultPort -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Validator -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.ViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Effect +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Validator +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.ViewModel class AccountIncomingConfigViewModel( private val validator: Validator, +// private val serverSettingsRepository: ServerConfigDomainContract.ServerSettingsRepository, private val accountStateRepository: AccountDomainContract.AccountStateRepository, initialState: State = State(), ) : BaseViewModel(initialState = initialState), ViewModel { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt similarity index 85% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt index e9d21564fe..f18164adb9 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt @@ -1,7 +1,7 @@ -package app.k9mail.feature.account.server.config.ui.incoming.fake +package app.k9mail.feature.account.server.settings.ui.incoming.fake import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract class FakeAccountIncomingConfigValidator( private val serverAnswer: ValidationResult = ValidationResult.Success, diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt new file mode 100644 index 0000000000..143c6c405a --- /dev/null +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt @@ -0,0 +1,22 @@ +package app.k9mail.feature.account.server.settings.ui.incoming.fake + +import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Effect +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.ViewModel + +class FakeAccountIncomingConfigViewModel( + initialState: State = State(), +) : BaseViewModel(initialState), ViewModel { + + val events = mutableListOf() + + override fun event(event: Event) { + events.add(event) + } + + fun effect(effect: Effect) { + emitEffect(effect) + } +} diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContent.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContent.kt similarity index 89% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContent.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContent.kt index 71b9236786..e1761f435a 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContent.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContent.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues @@ -27,11 +27,11 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.ui.item.defaultItemPadding -import app.k9mail.feature.account.server.config.R -import app.k9mail.feature.account.server.config.ui.common.ClientCertificateInput -import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.R +import app.k9mail.feature.account.server.settings.ui.common.ClientCertificateInput +import app.k9mail.feature.account.server.settings.ui.common.mapper.toResourceString +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State @Suppress("LongMethod") @Composable @@ -66,7 +66,7 @@ internal fun AccountOutgoingConfigContent( text = state.server.value, errorMessage = state.server.error?.toResourceString(resources), onTextChange = { onEvent(Event.ServerChanged(it)) }, - label = stringResource(id = R.string.account_server_config_server_label), + label = stringResource(id = R.string.account_server_settings_server_label), isRequired = true, contentPadding = defaultItemPadding(), ) @@ -78,7 +78,7 @@ internal fun AccountOutgoingConfigContent( optionToStringTransformation = { it.toResourceString(resources) }, selectedOption = state.security, onOptionChange = { onEvent(Event.SecurityChanged(it)) }, - label = stringResource(id = R.string.account_server_config_security_label), + label = stringResource(id = R.string.account_server_settings_security_label), contentPadding = defaultItemPadding(), ) } @@ -88,7 +88,7 @@ internal fun AccountOutgoingConfigContent( value = state.port.value, errorMessage = state.port.error?.toResourceString(resources), onValueChange = { onEvent(Event.PortChanged(it)) }, - label = stringResource(id = R.string.account_server_config_port_label), + label = stringResource(id = R.string.account_server_settings_port_label), isRequired = true, contentPadding = defaultItemPadding(), ) @@ -100,7 +100,7 @@ internal fun AccountOutgoingConfigContent( optionToStringTransformation = { it.toResourceString(resources) }, selectedOption = state.authenticationType, onOptionChange = { onEvent(Event.AuthenticationTypeChanged(it)) }, - label = stringResource(id = R.string.account_server_config_authentication_label), + label = stringResource(id = R.string.account_server_settings_authentication_label), contentPadding = defaultItemPadding(), ) } @@ -111,7 +111,7 @@ internal fun AccountOutgoingConfigContent( text = state.username.value, errorMessage = state.username.error?.toResourceString(resources), onTextChange = { onEvent(Event.UsernameChanged(it)) }, - label = stringResource(id = R.string.account_server_config_username_label), + label = stringResource(id = R.string.account_server_settings_username_label), isRequired = true, contentPadding = defaultItemPadding(), ) @@ -134,7 +134,7 @@ internal fun AccountOutgoingConfigContent( ClientCertificateInput( alias = state.clientCertificateAlias, onValueChange = { onEvent(Event.ClientCertificateChanged(it)) }, - label = stringResource(id = R.string.account_server_config_client_certificate_label), + label = stringResource(id = R.string.account_server_settings_client_certificate_label), contentPadding = defaultItemPadding(), ) } diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContract.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContract.kt similarity index 97% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContract.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContract.kt index 51cc1dd878..77c7e3e677 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigContract.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContract.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreen.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreen.kt similarity index 85% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreen.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreen.kt index 82a50f1504..f9b472eca7 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreen.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreen.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing import androidx.activity.compose.BackHandler import androidx.compose.runtime.Composable @@ -13,10 +13,10 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.ui.AccountTopAppBar import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository -import app.k9mail.feature.account.server.config.R -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.ViewModel +import app.k9mail.feature.account.server.settings.R +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Effect +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.ViewModel @Composable fun AccountOutgoingConfigScreen( @@ -43,7 +43,7 @@ fun AccountOutgoingConfigScreen( Scaffold( topBar = { AccountTopAppBar( - title = stringResource(id = R.string.account_server_config_outgoing_top_bar_title), + title = stringResource(id = R.string.account_server_settings_outgoing_top_bar_title), ) }, bottomBar = { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateExtensions.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateExtensions.kt similarity index 80% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateExtensions.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateExtensions.kt index a5b4544b00..945762c73e 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateExtensions.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateExtensions.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing internal val AccountOutgoingConfigContract.State.isUsernameFieldVisible: Boolean get() = authenticationType.isUsernameRequired diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapper.kt similarity index 92% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapper.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapper.kt index 5ff993d0d3..18cbb2085f 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapper.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapper.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.entity.toAuthType @@ -7,7 +7,7 @@ import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State import com.fsck.k9.mail.ServerSettings internal fun AccountState.toOutgoingConfigState(): State { diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigValidator.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigValidator.kt similarity index 70% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigValidator.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigValidator.kt index db073d78f6..951780d061 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigValidator.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigValidator.kt @@ -1,10 +1,10 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword -import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort -import app.k9mail.feature.account.server.config.domain.usecase.ValidateServer -import app.k9mail.feature.account.server.config.domain.usecase.ValidateUsername +import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePassword +import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePort +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateServer +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateUsername internal class AccountOutgoingConfigValidator( private val serverValidator: ValidateServer = ValidateServer(), diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModel.kt similarity index 85% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModel.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModel.kt index 50a96a14ef..6ece5c5d89 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModel.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModel.kt @@ -1,15 +1,15 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Validator -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.ViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Effect +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Validator +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.ViewModel class AccountOutgoingConfigViewModel( private val validator: Validator, diff --git a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt similarity index 83% rename from feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt index 4589ad7147..a1ebe20e84 100644 --- a/feature/account/server/config/src/main/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt @@ -1,7 +1,7 @@ -package app.k9mail.feature.account.server.config.ui.outgoing.fake +package app.k9mail.feature.account.server.settings.ui.outgoing.fake import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract class FakeAccountOutgoingConfigValidator( private val serverAnswer: ValidationResult = ValidationResult.Success, diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt new file mode 100644 index 0000000000..55905a1128 --- /dev/null +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt @@ -0,0 +1,22 @@ +package app.k9mail.feature.account.server.settings.ui.outgoing.fake + +import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Effect +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.ViewModel + +class FakeAccountOutgoingConfigViewModel( + initialState: State = State(), +) : BaseViewModel(initialState), ViewModel { + + val events = mutableListOf() + + override fun event(event: Event) { + events.add(event) + } + + fun effect(effect: Effect) { + emitEffect(effect) + } +} diff --git a/feature/account/server/settings/src/main/res/values/strings.xml b/feature/account/server/settings/src/main/res/values/strings.xml new file mode 100644 index 0000000000..4079537370 --- /dev/null +++ b/feature/account/server/settings/src/main/res/values/strings.xml @@ -0,0 +1,40 @@ + + + Protocol + Server + Security + Port + Authentication + Username + + None + StartTLS + SSL/TLS + + None + Normal password + Encrypted password + Client certificate + OAuth 2.0 + + None + Client certificate + + Incoming server settings + + Auto-detect IMAP namespace + IMAP path prefix + Use compression + Send client ID + + Outgoing server settings + + Email address is required. + Email address is invalid. + Server name is required. + Port is required. + Port is invalid (must be 1–65535). + Username is required. + Password is required. + Imap prefix can\'t be blank. + diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddressTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddressTest.kt similarity index 86% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddressTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddressTest.kt index 2549d11d11..225e6347bf 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateEmailAddressTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddressTest.kt @@ -1,7 +1,7 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError import assertk.assertThat import assertk.assertions.isInstanceOf import assertk.assertions.prop diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefixTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateImapPrefixTest.kt similarity index 93% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefixTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateImapPrefixTest.kt index 7b209f526b..4c38422c6c 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateImapPrefixTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateImapPrefixTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult import assertk.assertThat diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePasswordTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePasswordTest.kt similarity index 94% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePasswordTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePasswordTest.kt index 18f5fb6a26..d77f9a2579 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePasswordTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePasswordTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult import assertk.assertThat diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePortTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePortTest.kt similarity index 90% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePortTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePortTest.kt index 450667556d..c58d928896 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidatePortTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePortTest.kt @@ -1,7 +1,7 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.usecase.ValidatePort.ValidatePortError +import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePort.ValidatePortError import assertk.assertThat import assertk.assertions.isInstanceOf import assertk.assertions.prop diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServerTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateServerTest.kt similarity index 94% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServerTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateServerTest.kt index ac51fc7d55..0fbfa2b2fb 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateServerTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateServerTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult import assertk.assertThat diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsernameTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateUsernameTest.kt similarity index 94% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsernameTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateUsernameTest.kt index 4ac73fda0f..cca6628d12 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/domain/usecase/ValidateUsernameTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateUsernameTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.domain.usecase +package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult import assertk.assertThat diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreenKtTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreenKtTest.kt similarity index 75% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreenKtTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreenKtTest.kt index ac708f544b..170d77b4dc 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigScreenKtTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreenKtTest.kt @@ -1,10 +1,10 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.setContent -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.server.config.ui.incoming.fake.FakeAccountIncomingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Effect +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeAccountIncomingConfigViewModel import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt similarity index 95% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt index 5d146b07d9..436c25fe85 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity @@ -6,7 +6,7 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateTest.kt similarity index 89% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateTest.kt index 93d4460451..d3142d3c76 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigStateTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity @@ -6,7 +6,7 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModelTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModelTest.kt similarity index 97% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModelTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModelTest.kt index 7736113233..3651034b1c 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/incoming/AccountIncomingConfigViewModelTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModelTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.incoming +package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult @@ -18,10 +18,10 @@ import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort import app.k9mail.feature.account.common.domain.entity.toPop3DefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.server.config.ui.incoming.fake.FakeAccountIncomingConfigValidator +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Effect +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeAccountIncomingConfigValidator import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt similarity index 75% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt index b2bf06990c..52fe273f5f 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt @@ -1,10 +1,10 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.setContent -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.server.config.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Effect +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt similarity index 90% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt index f16773c9d9..543229d92d 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt @@ -1,11 +1,11 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateTest.kt similarity index 86% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateTest.kt index 6205639bfa..debee2e833 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigStateTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateTest.kt @@ -1,11 +1,11 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test diff --git a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModelTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModelTest.kt similarity index 96% rename from feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModelTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModelTest.kt index 92ad3ef3a8..ee79d75f60 100644 --- a/feature/account/server/config/src/test/kotlin/app/k9mail/feature/account/server/config/ui/outgoing/AccountOutgoingConfigViewModelTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModelTest.kt @@ -1,4 +1,4 @@ -package app.k9mail.feature.account.server.config.ui.outgoing +package app.k9mail.feature.account.server.settings.ui.outgoing import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult @@ -16,10 +16,10 @@ import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.server.config.ui.outgoing.fake.FakeAccountOutgoingConfigValidator +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Effect +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeAccountOutgoingConfigValidator import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType diff --git a/feature/account/setup/build.gradle.kts b/feature/account/setup/build.gradle.kts index 659472c308..29072b8e41 100644 --- a/feature/account/setup/build.gradle.kts +++ b/feature/account/setup/build.gradle.kts @@ -29,7 +29,7 @@ dependencies { api(projects.feature.account.common) implementation(projects.feature.account.oauth) - implementation(projects.feature.account.server.config) + implementation(projects.feature.account.server.settings) implementation(projects.feature.account.server.certificate) api(projects.feature.account.server.validation) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt index 6a2aee0c07..6dba0571d8 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt @@ -4,7 +4,7 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryService import app.k9mail.autodiscovery.service.RealAutoDiscoveryService import app.k9mail.feature.account.common.featureAccountCommonModule import app.k9mail.feature.account.oauth.featureAccountOAuthModule -import app.k9mail.feature.account.server.config.featureAccountServerConfigModule +import app.k9mail.feature.account.server.settings.featureAccountServerConfigModule import app.k9mail.feature.account.server.validation.featureAccountServerValidationModule import app.k9mail.feature.account.setup.domain.DomainContract import app.k9mail.feature.account.setup.domain.usecase.CreateAccount diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt index d2f9cc155e..27e4738f52 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt @@ -3,12 +3,12 @@ package app.k9mail.feature.account.setup.ui import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview import app.k9mail.core.ui.compose.common.mvi.observe -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigScreen -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigViewModel -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigScreen -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigScreen +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigScreen +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigViewModel import app.k9mail.feature.account.server.validation.KOIN_NAME_INCOMING_SERVER_VALIDATION import app.k9mail.feature.account.server.validation.KOIN_NAME_OUTGOING_SERVER_VALIDATION import app.k9mail.feature.account.server.validation.ui.ServerValidationContract diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt index 76f1599846..eee56e35f5 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt @@ -5,8 +5,8 @@ import app.k9mail.autodiscovery.api.SmtpServerSettings import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toIncomingProtocolType diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt index a6b8ca3e6d..ebe4c7e1cf 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt @@ -1,9 +1,9 @@ package app.k9mail.feature.account.setup.ui.autodiscovery import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.config.domain.ServerConfigDomainContract -import app.k9mail.feature.account.server.config.domain.usecase.ValidateEmailAddress -import app.k9mail.feature.account.server.config.domain.usecase.ValidatePassword +import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract +import app.k9mail.feature.account.server.settings.domain.usecase.ValidateEmailAddress +import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePassword import app.k9mail.feature.account.setup.domain.DomainContract.UseCase import app.k9mail.feature.account.setup.domain.usecase.ValidateConfigurationApproval diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/EmailAddressItem.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/EmailAddressItem.kt index de73de1061..b4fd9d522f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/EmailAddressItem.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/EmailAddressItem.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.platform.LocalContext import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.ui.compose.designsystem.molecule.input.EmailAddressInput import app.k9mail.feature.account.common.ui.item.ListItem -import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString +import app.k9mail.feature.account.server.settings.ui.common.mapper.toResourceString @Composable internal fun LazyItemScope.EmailAddressItem( diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/PasswordItem.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/PasswordItem.kt index 6e613e2f33..2b5447989c 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/PasswordItem.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/item/PasswordItem.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.platform.LocalContext import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.ui.compose.designsystem.molecule.input.PasswordInput import app.k9mail.feature.account.common.ui.item.ListItem -import app.k9mail.feature.account.server.config.ui.common.mapper.toResourceString +import app.k9mail.feature.account.server.settings.ui.common.mapper.toResourceString @Composable internal fun LazyItemScope.PasswordItem( diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index c568c561fc..a85f9c8971 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -5,8 +5,8 @@ import app.k9mail.core.common.oauth.OAuthConfigurationFactory import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.server.validation.ui.ServerValidationContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt index 0c1ddb272a..8358f53c8a 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt @@ -4,8 +4,8 @@ import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.onNodeWithTag import app.k9mail.core.ui.compose.testing.setContent import app.k9mail.core.ui.compose.theme.ThunderbirdTheme -import app.k9mail.feature.account.server.config.ui.incoming.fake.FakeAccountIncomingConfigViewModel -import app.k9mail.feature.account.server.config.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeAccountIncomingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel import app.k9mail.feature.account.server.validation.ui.fake.FakeServerValidationViewModel import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt index 4e668b7366..00763c669b 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt @@ -10,8 +10,8 @@ import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.config.ui.incoming.AccountIncomingConfigContract -import app.k9mail.feature.account.server.config.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity diff --git a/settings.gradle.kts b/settings.gradle.kts index 63a7f0fb68..4e7da6fab2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -48,7 +48,7 @@ include( ":feature:account:oauth", ":feature:account:setup", ":feature:account:server:certificate", - ":feature:account:server:config", + ":feature:account:server:settings", ":feature:account:server:validation", ) -- GitLab From 2c0a22a78a65d9d6b0845936e4bf3da11582c7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 13:31:47 +0200 Subject: [PATCH 29/94] Rename ServerConfigDomainContract to ServerSettingsDomainContract --- ...figDomainContract.kt => ServerSettingsDomainContract.kt} | 2 +- .../server/settings/domain/usecase/ValidateEmailAddress.kt | 2 +- .../server/settings/domain/usecase/ValidateImapPrefix.kt | 2 +- .../server/settings/domain/usecase/ValidatePassword.kt | 2 +- .../account/server/settings/domain/usecase/ValidatePort.kt | 2 +- .../server/settings/domain/usecase/ValidateServer.kt | 2 +- .../server/settings/domain/usecase/ValidateUsername.kt | 2 +- .../settings/ui/incoming/AccountIncomingConfigValidator.kt | 2 +- .../setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt | 6 +++--- 9 files changed, 11 insertions(+), 11 deletions(-) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/{ServerConfigDomainContract.kt => ServerSettingsDomainContract.kt} (95%) diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerConfigDomainContract.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerSettingsDomainContract.kt similarity index 95% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerConfigDomainContract.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerSettingsDomainContract.kt index 6a1b0cf526..0bc312dcd8 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerConfigDomainContract.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerSettingsDomainContract.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.server.settings.domain import app.k9mail.core.common.domain.usecase.validation.ValidationResult -interface ServerConfigDomainContract { +interface ServerSettingsDomainContract { interface UseCase { diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddress.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddress.kt index 0548e11c05..994348620f 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddress.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddress.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerSettingsDomainContract.UseCase class ValidateEmailAddress : UseCase.ValidateEmailAddress { diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateImapPrefix.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateImapPrefix.kt index d180d61a59..0866803b46 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateImapPrefix.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateImapPrefix.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerSettingsDomainContract.UseCase internal class ValidateImapPrefix : UseCase.ValidateImapPrefix { diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePassword.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePassword.kt index 00389b1853..04cb48414b 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePassword.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePassword.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerSettingsDomainContract.UseCase class ValidatePassword : UseCase.ValidatePassword { diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePort.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePort.kt index e27e3c7fb8..4c5f7a5507 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePort.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidatePort.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerSettingsDomainContract.UseCase internal class ValidatePort : UseCase.ValidatePort { diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateServer.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateServer.kt index c264c4e4f6..0a4e6a122a 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateServer.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateServer.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerSettingsDomainContract.UseCase internal class ValidateServer : UseCase.ValidateServer { diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateUsername.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateUsername.kt index 647e80064c..34ea8dfad1 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateUsername.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateUsername.kt @@ -2,7 +2,7 @@ package app.k9mail.feature.account.server.settings.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerSettingsDomainContract.UseCase internal class ValidateUsername : UseCase.ValidateUsername { diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigValidator.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigValidator.kt index 27a8e5a4ff..b76a1d67d1 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigValidator.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigValidator.kt @@ -1,7 +1,7 @@ package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract.UseCase +import app.k9mail.feature.account.server.settings.domain.ServerSettingsDomainContract.UseCase import app.k9mail.feature.account.server.settings.domain.usecase.ValidateImapPrefix import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePassword import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePort diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt index ebe4c7e1cf..8544218d5f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt @@ -1,15 +1,15 @@ package app.k9mail.feature.account.setup.ui.autodiscovery import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.ServerConfigDomainContract import app.k9mail.feature.account.server.settings.domain.usecase.ValidateEmailAddress import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePassword import app.k9mail.feature.account.setup.domain.DomainContract.UseCase import app.k9mail.feature.account.setup.domain.usecase.ValidateConfigurationApproval +import app.k9mail.feature.account.server.settings.domain.ServerSettingsDomainContract.UseCase as ServerSettingsUseCase internal class AccountAutoDiscoveryValidator( - private val emailAddressValidator: ServerConfigDomainContract.UseCase.ValidateEmailAddress = ValidateEmailAddress(), - private val passwordValidator: ServerConfigDomainContract.UseCase.ValidatePassword = ValidatePassword(), + private val emailAddressValidator: ServerSettingsUseCase.ValidateEmailAddress = ValidateEmailAddress(), + private val passwordValidator: ServerSettingsUseCase.ValidatePassword = ValidatePassword(), private val configurationApprovalValidator: UseCase.ValidateConfigurationApproval = ValidateConfigurationApproval(), ) : AccountAutoDiscoveryContract.Validator { -- GitLab From 4926f595fbf21e46bb00f7a299d1901482456e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 14:11:33 +0200 Subject: [PATCH 30/94] Rename AccountIncomingConfig to IncomingServerSettings --- .../server/settings/ServerConfigModule.kt | 10 +++---- ...nt.kt => IncomingServerSettingsContent.kt} | 16 +++++------ ...t.kt => IncomingServerSettingsContract.kt} | 2 +- ...een.kt => IncomingServerSettingsScreen.kt} | 28 +++++++++---------- ... IncomingServerSettingsStateExtensions.kt} | 4 +-- ...t => IncomingServerSettingsStateMapper.kt} | 2 +- ....kt => IncomingServerSettingsValidator.kt} | 4 +-- ....kt => IncomingServerSettingsViewModel.kt} | 12 ++++---- .../FakeAccountIncomingConfigViewModel.kt | 22 --------------- ...=> FakeIncomingServerSettingsValidator.kt} | 6 ++-- .../FakeIncomingServerSettingsViewModel.kt | 22 +++++++++++++++ ... IncomingServerSettingsConfigStateTest.kt} | 4 +-- ... => IncomingServerSettingsScreenKtTest.kt} | 12 ++++---- ...ncomingServerSettingsStateMapperKtTest.kt} | 4 +-- ...=> IncomingServerSettingsViewModelTest.kt} | 19 ++++++------- .../account/setup/ui/AccountSetupScreen.kt | 10 +++---- .../AccountAutoDiscoveryStateMapper.kt | 8 +++--- .../account/setup/AccountSetupModuleKtTest.kt | 4 +-- .../setup/ui/AccountSetupScreenKtTest.kt | 8 +++--- .../AccountAutoDiscoveryStateMapperKtTest.kt | 10 +++---- 20 files changed, 103 insertions(+), 104 deletions(-) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigContent.kt => IncomingServerSettingsContent.kt} (94%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigContract.kt => IncomingServerSettingsContract.kt} (98%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigScreen.kt => IncomingServerSettingsScreen.kt} (72%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigStateExtensions.kt => IncomingServerSettingsStateExtensions.kt} (84%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigStateMapper.kt => IncomingServerSettingsStateMapper.kt} (96%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigValidator.kt => IncomingServerSettingsValidator.kt} (94%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigViewModel.kt => IncomingServerSettingsViewModel.kt} (90%) delete mode 100644 feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/{FakeAccountIncomingConfigValidator.kt => FakeIncomingServerSettingsValidator.kt} (83%) create mode 100644 feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeIncomingServerSettingsViewModel.kt rename feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigStateTest.kt => IncomingServerSettingsConfigStateTest.kt} (90%) rename feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigScreenKtTest.kt => IncomingServerSettingsScreenKtTest.kt} (72%) rename feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigStateMapperKtTest.kt => IncomingServerSettingsStateMapperKtTest.kt} (95%) rename feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/{AccountIncomingConfigViewModelTest.kt => IncomingServerSettingsViewModelTest.kt} (95%) diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt index 638e4b0101..a32ebd165b 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt @@ -1,8 +1,8 @@ package app.k9mail.feature.account.server.settings -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigValidator -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsValidator +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsViewModel import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigValidator import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigViewModel @@ -11,11 +11,11 @@ import org.koin.core.module.Module import org.koin.dsl.module val featureAccountServerConfigModule: Module = module { - factory { AccountIncomingConfigValidator() } + factory { IncomingServerSettingsValidator() } factory { AccountOutgoingConfigValidator() } viewModel { - AccountIncomingConfigViewModel( + IncomingServerSettingsViewModel( validator = get(), accountStateRepository = get(), ) diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContent.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsContent.kt similarity index 94% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContent.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsContent.kt index 247fbe5d90..447e6beb40 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContent.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsContent.kt @@ -31,12 +31,12 @@ import app.k9mail.feature.account.common.ui.item.defaultItemPadding import app.k9mail.feature.account.server.settings.R import app.k9mail.feature.account.server.settings.ui.common.ClientCertificateInput import app.k9mail.feature.account.server.settings.ui.common.mapper.toResourceString -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State @Suppress("LongMethod") @Composable -internal fun AccountIncomingConfigContent( +internal fun IncomingServerSettingsContent( state: State, onEvent: (Event) -> Unit, contentPadding: PaddingValues, @@ -46,7 +46,7 @@ internal fun AccountIncomingConfigContent( ResponsiveWidthContainer( modifier = Modifier - .testTag("AccountIncomingConfigContent") + .testTag("IncomingServerSettingsContent") .padding(contentPadding) .fillMaxWidth() .then(modifier), @@ -197,9 +197,9 @@ internal fun AccountIncomingConfigContent( @Composable @DevicePreviews -internal fun AccountIncomingConfigContentK9Preview() { +internal fun IncomingServerSettingsContentK9Preview() { K9Theme { - AccountIncomingConfigContent( + IncomingServerSettingsContent( onEvent = { }, state = State(), contentPadding = PaddingValues(), @@ -209,9 +209,9 @@ internal fun AccountIncomingConfigContentK9Preview() { @Composable @DevicePreviews -internal fun AccountIncomingConfigContentThunderbirdPreview() { +internal fun IncomingServerSettingsContentThunderbirdPreview() { ThunderbirdTheme { - AccountIncomingConfigContent( + IncomingServerSettingsContent( onEvent = { }, state = State(), contentPadding = PaddingValues(), diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContract.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsContract.kt similarity index 98% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContract.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsContract.kt index 4331a81209..07e203f1e7 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigContract.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsContract.kt @@ -9,7 +9,7 @@ import app.k9mail.feature.account.common.domain.entity.toDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -interface AccountIncomingConfigContract { +interface IncomingServerSettingsContract { interface ViewModel : UnidirectionalViewModel diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreen.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsScreen.kt similarity index 72% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreen.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsScreen.kt index cbcd361f8f..9340103d7d 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreen.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsScreen.kt @@ -14,13 +14,13 @@ import app.k9mail.feature.account.common.ui.AccountTopAppBar import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.server.settings.R -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.ViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Effect +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.ViewModel @Composable -fun AccountIncomingConfigScreen( - onNext: (AccountIncomingConfigContract.State) -> Unit, +fun IncomingServerSettingsScreen( + onNext: (IncomingServerSettingsContract.State) -> Unit, onBack: () -> Unit, viewModel: ViewModel, modifier: Modifier = Modifier, @@ -54,7 +54,7 @@ fun AccountIncomingConfigScreen( }, modifier = modifier, ) { innerPadding -> - AccountIncomingConfigContent( + IncomingServerSettingsContent( onEvent = { dispatch(it) }, state = state.value, contentPadding = innerPadding, @@ -64,13 +64,13 @@ fun AccountIncomingConfigScreen( @Composable @DevicePreviews -internal fun AccountIncomingConfigScreenK9Preview() { +internal fun IncomingServerSettingsScreenK9Preview() { K9Theme { - AccountIncomingConfigScreen( + IncomingServerSettingsScreen( onNext = {}, onBack = {}, - viewModel = AccountIncomingConfigViewModel( - validator = AccountIncomingConfigValidator(), + viewModel = IncomingServerSettingsViewModel( + validator = IncomingServerSettingsValidator(), accountStateRepository = PreviewAccountStateRepository(), ), ) @@ -79,13 +79,13 @@ internal fun AccountIncomingConfigScreenK9Preview() { @Composable @DevicePreviews -internal fun AccountIncomingConfigScreenThunderbirdPreview() { +internal fun IncomingServerSettingsScreenThunderbirdPreview() { ThunderbirdTheme { - AccountIncomingConfigScreen( + IncomingServerSettingsScreen( onNext = {}, onBack = {}, - viewModel = AccountIncomingConfigViewModel( - validator = AccountIncomingConfigValidator(), + viewModel = IncomingServerSettingsViewModel( + validator = IncomingServerSettingsValidator(), accountStateRepository = PreviewAccountStateRepository(), ), ) diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateExtensions.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateExtensions.kt similarity index 84% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateExtensions.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateExtensions.kt index 3949c56a01..8b32668102 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateExtensions.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateExtensions.kt @@ -5,10 +5,10 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList -internal val AccountIncomingConfigContract.State.isPasswordFieldVisible: Boolean +internal val IncomingServerSettingsContract.State.isPasswordFieldVisible: Boolean get() = authenticationType.isPasswordRequired -internal val AccountIncomingConfigContract.State.allowedAuthenticationTypes: ImmutableList +internal val IncomingServerSettingsContract.State.allowedAuthenticationTypes: ImmutableList get() = protocolType.allowedAuthenticationTypes.toImmutableList() internal val IncomingProtocolType.allowedAuthenticationTypes: List diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt similarity index 96% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapper.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt index 3f27078971..89607a1d8a 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapper.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt @@ -8,7 +8,7 @@ import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.store.imap.ImapStoreSettings diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigValidator.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsValidator.kt similarity index 94% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigValidator.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsValidator.kt index b76a1d67d1..8f4bc935f5 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigValidator.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsValidator.kt @@ -8,13 +8,13 @@ import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePort import app.k9mail.feature.account.server.settings.domain.usecase.ValidateServer import app.k9mail.feature.account.server.settings.domain.usecase.ValidateUsername -internal class AccountIncomingConfigValidator( +internal class IncomingServerSettingsValidator( private val serverValidator: UseCase.ValidateServer = ValidateServer(), private val portValidator: UseCase.ValidatePort = ValidatePort(), private val usernameValidator: UseCase.ValidateUsername = ValidateUsername(), private val passwordValidator: UseCase.ValidatePassword = ValidatePassword(), private val imapPrefixValidator: UseCase.ValidateImapPrefix = ValidateImapPrefix(), -) : AccountIncomingConfigContract.Validator { +) : IncomingServerSettingsContract.Validator { override fun validateServer(server: String): ValidationResult { return serverValidator.execute(server) } diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt similarity index 90% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModel.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt index fa4a1a7bdf..2fcd516201 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModel.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt @@ -6,13 +6,13 @@ import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.toDefaultPort -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Validator -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.ViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Effect +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Validator +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.ViewModel -class AccountIncomingConfigViewModel( +class IncomingServerSettingsViewModel( private val validator: Validator, // private val serverSettingsRepository: ServerConfigDomainContract.ServerSettingsRepository, private val accountStateRepository: AccountDomainContract.AccountStateRepository, diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt deleted file mode 100644 index 143c6c405a..0000000000 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigViewModel.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.k9mail.feature.account.server.settings.ui.incoming.fake - -import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.ViewModel - -class FakeAccountIncomingConfigViewModel( - initialState: State = State(), -) : BaseViewModel(initialState), ViewModel { - - val events = mutableListOf() - - override fun event(event: Event) { - events.add(event) - } - - fun effect(effect: Effect) { - emitEffect(effect) - } -} diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeIncomingServerSettingsValidator.kt similarity index 83% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeIncomingServerSettingsValidator.kt index f18164adb9..c8762b2139 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeAccountIncomingConfigValidator.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeIncomingServerSettingsValidator.kt @@ -1,15 +1,15 @@ package app.k9mail.feature.account.server.settings.ui.incoming.fake import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract -class FakeAccountIncomingConfigValidator( +class FakeIncomingServerSettingsValidator( private val serverAnswer: ValidationResult = ValidationResult.Success, private val portAnswer: ValidationResult = ValidationResult.Success, private val usernameAnswer: ValidationResult = ValidationResult.Success, private val passwordAnswer: ValidationResult = ValidationResult.Success, private val imapPrefixAnswer: ValidationResult = ValidationResult.Success, -) : AccountIncomingConfigContract.Validator { +) : IncomingServerSettingsContract.Validator { override fun validateServer(server: String): ValidationResult = serverAnswer override fun validatePort(port: Long?): ValidationResult = portAnswer override fun validateUsername(username: String): ValidationResult = usernameAnswer diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeIncomingServerSettingsViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeIncomingServerSettingsViewModel.kt new file mode 100644 index 0000000000..dec4c3a759 --- /dev/null +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/fake/FakeIncomingServerSettingsViewModel.kt @@ -0,0 +1,22 @@ +package app.k9mail.feature.account.server.settings.ui.incoming.fake + +import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Effect +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.ViewModel + +class FakeIncomingServerSettingsViewModel( + initialState: State = State(), +) : BaseViewModel(initialState), ViewModel { + + val events = mutableListOf() + + override fun event(event: Event) { + events.add(event) + } + + fun effect(effect: Effect) { + emitEffect(effect) + } +} diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsConfigStateTest.kt similarity index 90% rename from feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsConfigStateTest.kt index d3142d3c76..a30aacf261 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsConfigStateTest.kt @@ -6,12 +6,12 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test -class AccountIncomingConfigStateTest { +class IncomingServerSettingsConfigStateTest { @Test fun `should set default values`() { diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreenKtTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsScreenKtTest.kt similarity index 72% rename from feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreenKtTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsScreenKtTest.kt index 170d77b4dc..26591d87a7 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigScreenKtTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsScreenKtTest.kt @@ -2,25 +2,25 @@ package app.k9mail.feature.account.server.settings.ui.incoming import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.setContent -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeAccountIncomingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Effect +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeIncomingServerSettingsViewModel import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest import org.junit.Test -class AccountIncomingConfigScreenKtTest : ComposeTest() { +class IncomingServerSettingsScreenKtTest : ComposeTest() { @Test fun `should delegate navigation effects`() = runTest { val initialState = State() - val viewModel = FakeAccountIncomingConfigViewModel(initialState) + val viewModel = FakeIncomingServerSettingsViewModel(initialState) var onNextCounter = 0 var onBackCounter = 0 setContent { - AccountIncomingConfigScreen( + IncomingServerSettingsScreen( onNext = { onNextCounter++ }, onBack = { onBackCounter++ }, viewModel = viewModel, diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapperKtTest.kt similarity index 95% rename from feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapperKtTest.kt index 436c25fe85..31c48ba61c 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigStateMapperKtTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapperKtTest.kt @@ -6,7 +6,7 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType @@ -14,7 +14,7 @@ import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.store.imap.ImapStoreSettings import org.junit.Test -class AccountIncomingConfigStateMapperKtTest { +class IncomingServerSettingsStateMapperKtTest { @Test fun `should map to IMAP server settings`() { diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModelTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt similarity index 95% rename from feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModelTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt index 3651034b1c..fc4bf185e7 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/AccountIncomingConfigViewModelTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt @@ -5,7 +5,6 @@ import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.testing.MainDispatcherRule import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.eventStateTest -import app.k9mail.core.ui.compose.testing.mvi.turbines import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.AccountDomainContract @@ -18,10 +17,10 @@ import app.k9mail.feature.account.common.domain.entity.toImapDefaultPort import app.k9mail.feature.account.common.domain.entity.toPop3DefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Effect -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.Event -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract.State -import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeAccountIncomingConfigValidator +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Effect +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeIncomingServerSettingsValidator import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType @@ -30,7 +29,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -class AccountIncomingConfigViewModelTest { +class IncomingServerSettingsViewModelTest { @get:Rule val mainDispatcherRule = MainDispatcherRule() @@ -348,8 +347,8 @@ class AccountIncomingConfigViewModelTest { @Test fun `should change state and not emit NavigateNext effect when OnNextClicked event received and input invalid`() = runTest { - val testSubject = AccountIncomingConfigViewModel( - validator = FakeAccountIncomingConfigValidator( + val testSubject = IncomingServerSettingsViewModel( + validator = FakeIncomingServerSettingsValidator( serverAnswer = ValidationResult.Failure(TestError), ), accountStateRepository = InMemoryAccountStateRepository(), @@ -394,9 +393,9 @@ class AccountIncomingConfigViewModelTest { private companion object { fun createTestSubject( initialState: State = State(), - validator: AccountIncomingConfigContract.Validator = FakeAccountIncomingConfigValidator(), + validator: IncomingServerSettingsContract.Validator = FakeIncomingServerSettingsValidator(), repository: AccountDomainContract.AccountStateRepository = InMemoryAccountStateRepository(), - ) = AccountIncomingConfigViewModel( + ) = IncomingServerSettingsViewModel( validator = validator, accountStateRepository = repository, initialState = initialState, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt index 27e4738f52..e6a76ee61f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt @@ -3,9 +3,9 @@ package app.k9mail.feature.account.setup.ui import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview import app.k9mail.core.ui.compose.common.mvi.observe -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigScreen -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsScreen +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsViewModel import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigScreen import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigViewModel @@ -34,7 +34,7 @@ fun AccountSetupScreen( onBack: () -> Unit, viewModel: ViewModel = koinViewModel(), autoDiscoveryViewModel: AccountAutoDiscoveryContract.ViewModel = koinViewModel(), - incomingViewModel: AccountIncomingConfigContract.ViewModel = koinViewModel(), + incomingViewModel: IncomingServerSettingsContract.ViewModel = koinViewModel(), incomingValidationViewModel: ServerValidationContract.ViewModel = koinViewModel( named(KOIN_NAME_INCOMING_SERVER_VALIDATION), ), @@ -67,7 +67,7 @@ fun AccountSetupScreen( } SetupStep.INCOMING_CONFIG -> { - AccountIncomingConfigScreen( + IncomingServerSettingsScreen( onNext = { dispatch(Event.OnNext) }, onBack = { dispatch(Event.OnBack) }, viewModel = incomingViewModel, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt index eee56e35f5..92c23874aa 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt @@ -5,7 +5,7 @@ import app.k9mail.autodiscovery.api.SmtpServerSettings import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity @@ -23,15 +23,15 @@ internal fun AccountAutoDiscoveryContract.State.toAccountState(): AccountState { ) } -internal fun AccountAutoDiscoveryContract.State.toIncomingConfigState(): AccountIncomingConfigContract.State { +internal fun AccountAutoDiscoveryContract.State.toIncomingConfigState(): IncomingServerSettingsContract.State { val incomingSettings = autoDiscoverySettings?.incomingServerSettings as? ImapServerSettings? return if (incomingSettings == null) { - AccountIncomingConfigContract.State( + IncomingServerSettingsContract.State( username = StringInputField(value = emailAddress.value), password = StringInputField(value = password.value), ) } else { - AccountIncomingConfigContract.State( + IncomingServerSettingsContract.State( protocolType = incomingSettings.toIncomingProtocolType(), server = StringInputField(value = incomingSettings.hostname.value), security = incomingSettings.connectionSecurity.toConnectionSecurity(), diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index a85f9c8971..c0a33084c6 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -5,7 +5,7 @@ import app.k9mail.core.common.oauth.OAuthConfigurationFactory import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.server.validation.ui.ServerValidationContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator @@ -65,7 +65,7 @@ class AccountSetupModuleKtTest : KoinTest { AccountAutoDiscoveryContract.State::class, AccountOAuthContract.State::class, ServerValidationContract.State::class, - AccountIncomingConfigContract.State::class, + IncomingServerSettingsContract.State::class, AccountOutgoingConfigContract.State::class, AccountOptionsContract.State::class, AccountState::class, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt index 8358f53c8a..7dc4f11668 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt @@ -4,7 +4,7 @@ import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.onNodeWithTag import app.k9mail.core.ui.compose.testing.setContent import app.k9mail.core.ui.compose.theme.ThunderbirdTheme -import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeAccountIncomingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeIncomingServerSettingsViewModel import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel import app.k9mail.feature.account.server.validation.ui.fake.FakeServerValidationViewModel import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect @@ -30,7 +30,7 @@ class AccountSetupScreenKtTest : ComposeTest() { onBack = { }, viewModel = viewModel, autoDiscoveryViewModel = FakeAccountAutoDiscoveryViewModel(), - incomingViewModel = FakeAccountIncomingConfigViewModel(), + incomingViewModel = FakeIncomingServerSettingsViewModel(), incomingValidationViewModel = FakeServerValidationViewModel(), outgoingViewModel = FakeAccountOutgoingConfigViewModel(), outgoingValidationViewModel = FakeServerValidationViewModel(), @@ -59,7 +59,7 @@ class AccountSetupScreenKtTest : ComposeTest() { onBack = { onBackCounter++ }, viewModel = viewModel, autoDiscoveryViewModel = FakeAccountAutoDiscoveryViewModel(), - incomingViewModel = FakeAccountIncomingConfigViewModel(), + incomingViewModel = FakeIncomingServerSettingsViewModel(), incomingValidationViewModel = FakeServerValidationViewModel(), outgoingViewModel = FakeAccountOutgoingConfigViewModel(), outgoingValidationViewModel = FakeServerValidationViewModel(), @@ -84,7 +84,7 @@ class AccountSetupScreenKtTest : ComposeTest() { private fun getTagForStep(step: SetupStep): String = when (step) { SetupStep.AUTO_CONFIG -> "AccountAutoDiscoveryContent" - SetupStep.INCOMING_CONFIG -> "AccountIncomingConfigContent" + SetupStep.INCOMING_CONFIG -> "IncomingServerSettingsContent" SetupStep.INCOMING_VALIDATION -> "AccountValidationContent" SetupStep.OUTGOING_CONFIG -> "AccountOutgoingConfigContent" SetupStep.OUTGOING_VALIDATION -> "AccountValidationContent" diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt index 00763c669b..076b9f3b9d 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt @@ -10,7 +10,7 @@ import app.k9mail.feature.account.common.domain.entity.AuthenticationType import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.settings.ui.incoming.AccountIncomingConfigContract +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity @@ -41,7 +41,7 @@ class AccountAutoDiscoveryStateMapperKtTest { fun `should map to default IncomingConfigState when empty`() { val incomingConfigState = EMPTY_STATE.toIncomingConfigState() - assertThat(incomingConfigState).isEqualTo(AccountIncomingConfigContract.State()) + assertThat(incomingConfigState).isEqualTo(IncomingServerSettingsContract.State()) } @Test @@ -49,7 +49,7 @@ class AccountAutoDiscoveryStateMapperKtTest { val incomingConfigState = EMAIL_PASSWORD_STATE.toIncomingConfigState() assertThat(incomingConfigState).isEqualTo( - AccountIncomingConfigContract.State( + IncomingServerSettingsContract.State( username = StringInputField(value = EMAIL_ADDRESS), password = StringInputField(value = PASSWORD), ), @@ -61,7 +61,7 @@ class AccountAutoDiscoveryStateMapperKtTest { val incomingConfigState = AUTO_DISCOVERY_STATE.toIncomingConfigState() assertThat(incomingConfigState).isEqualTo( - AccountIncomingConfigContract.State( + IncomingServerSettingsContract.State( protocolType = IncomingProtocolType.IMAP, server = StringInputField(value = AUTO_DISCOVERY_HOSTNAME.value), security = AUTO_DISCOVERY_SECURITY.toConnectionSecurity(), @@ -78,7 +78,7 @@ class AccountAutoDiscoveryStateMapperKtTest { val incomingConfigState = AUTO_DISCOVERY_STATE_USERNAME_EMPTY.toIncomingConfigState() assertThat(incomingConfigState).isEqualTo( - AccountIncomingConfigContract.State( + IncomingServerSettingsContract.State( protocolType = IncomingProtocolType.IMAP, server = StringInputField(value = AUTO_DISCOVERY_HOSTNAME.value), security = AUTO_DISCOVERY_SECURITY.toConnectionSecurity(), -- GitLab From e152c1f2d13c2ccb964b90670962ece348bf6c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 14:19:50 +0200 Subject: [PATCH 31/94] Rename AccountOutgoingConfig to OutgoingServerSettings --- .../server/settings/ServerConfigModule.kt | 10 +++---- ...nt.kt => OutgoingServerSettingsContent.kt} | 16 ++++++------ ...t.kt => OutgoingServerSettingsContract.kt} | 2 +- ...een.kt => OutgoingServerSettingsScreen.kt} | 26 +++++++++---------- ... OutgoingServerSettingsStateExtensions.kt} | 4 +-- ...t => OutgoingServerSettingsStateMapper.kt} | 2 +- ....kt => OutgoingServerSettingsValidator.kt} | 4 +-- ....kt => OutgoingServerSettingsViewModel.kt} | 12 ++++----- .../FakeAccountOutgoingConfigViewModel.kt | 22 ---------------- ...=> FakeOutgoingServerSettingsValidator.kt} | 6 ++--- .../FakeOutgoingServerSettingsViewModel.kt | 22 ++++++++++++++++ ... => OutgoingServerSettingsScreenKtTest.kt} | 12 ++++----- ...utgoingServerSettingsStateMapperKtTest.kt} | 4 +-- ....kt => OutgoingServerSettingsStateTest.kt} | 4 +-- ...=> OutgoingServerSettingsViewModelTest.kt} | 17 ++++++------ .../account/setup/ui/AccountSetupScreen.kt | 10 +++---- .../AccountAutoDiscoveryStateMapper.kt | 8 +++--- .../account/setup/AccountSetupModuleKtTest.kt | 4 +-- .../setup/ui/AccountSetupScreenKtTest.kt | 8 +++--- .../AccountAutoDiscoveryStateMapperKtTest.kt | 10 +++---- 20 files changed, 101 insertions(+), 102 deletions(-) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigContent.kt => OutgoingServerSettingsContent.kt} (92%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigContract.kt => OutgoingServerSettingsContract.kt} (98%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigScreen.kt => OutgoingServerSettingsScreen.kt} (73%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigStateExtensions.kt => OutgoingServerSettingsStateExtensions.kt} (50%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigStateMapper.kt => OutgoingServerSettingsStateMapper.kt} (95%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigValidator.kt => OutgoingServerSettingsValidator.kt} (92%) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigViewModel.kt => OutgoingServerSettingsViewModel.kt} (86%) delete mode 100644 feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/{FakeAccountOutgoingConfigValidator.kt => FakeOutgoingServerSettingsValidator.kt} (80%) create mode 100644 feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeOutgoingServerSettingsViewModel.kt rename feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigScreenKtTest.kt => OutgoingServerSettingsScreenKtTest.kt} (72%) rename feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigStateMapperKtTest.kt => OutgoingServerSettingsStateMapperKtTest.kt} (91%) rename feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigStateTest.kt => OutgoingServerSettingsStateTest.kt} (88%) rename feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/{AccountOutgoingConfigViewModelTest.kt => OutgoingServerSettingsViewModelTest.kt} (94%) diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt index a32ebd165b..1af9721aa1 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt @@ -3,16 +3,16 @@ package app.k9mail.feature.account.server.settings import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsValidator import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsViewModel -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigValidator -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsValidator +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsViewModel import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.core.module.Module import org.koin.dsl.module val featureAccountServerConfigModule: Module = module { factory { IncomingServerSettingsValidator() } - factory { AccountOutgoingConfigValidator() } + factory { OutgoingServerSettingsValidator() } viewModel { IncomingServerSettingsViewModel( @@ -22,7 +22,7 @@ val featureAccountServerConfigModule: Module = module { } viewModel { - AccountOutgoingConfigViewModel( + OutgoingServerSettingsViewModel( validator = get(), accountStateRepository = get(), ) diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContent.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsContent.kt similarity index 92% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContent.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsContent.kt index e1761f435a..61a07cc54a 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContent.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsContent.kt @@ -30,12 +30,12 @@ import app.k9mail.feature.account.common.ui.item.defaultItemPadding import app.k9mail.feature.account.server.settings.R import app.k9mail.feature.account.server.settings.ui.common.ClientCertificateInput import app.k9mail.feature.account.server.settings.ui.common.mapper.toResourceString -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State @Suppress("LongMethod") @Composable -internal fun AccountOutgoingConfigContent( +internal fun OutgoingServerSettingsContent( state: State, onEvent: (Event) -> Unit, contentPadding: PaddingValues, @@ -45,7 +45,7 @@ internal fun AccountOutgoingConfigContent( ResponsiveWidthContainer( modifier = Modifier - .testTag("AccountOutgoingConfigContent") + .testTag("OutgoingServerSettingsContent") .padding(contentPadding) .fillMaxWidth() .then(modifier), @@ -144,9 +144,9 @@ internal fun AccountOutgoingConfigContent( @Composable @DevicePreviews -internal fun AccountOutgoingConfigContentK9Preview() { +internal fun OutgoingServerSettingsContentK9Preview() { K9Theme { - AccountOutgoingConfigContent( + OutgoingServerSettingsContent( onEvent = { }, state = State(), contentPadding = PaddingValues(), @@ -156,9 +156,9 @@ internal fun AccountOutgoingConfigContentK9Preview() { @Composable @DevicePreviews -internal fun AccountOutgoingConfigContentThunderbirdPreview() { +internal fun OutgoingServerSettingsContentThunderbirdPreview() { ThunderbirdTheme { - AccountOutgoingConfigContent( + OutgoingServerSettingsContent( onEvent = { }, state = State(), contentPadding = PaddingValues(), diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContract.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsContract.kt similarity index 98% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContract.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsContract.kt index 77c7e3e677..27c6dce5f1 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigContract.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsContract.kt @@ -8,7 +8,7 @@ import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -interface AccountOutgoingConfigContract { +interface OutgoingServerSettingsContract { interface ViewModel : UnidirectionalViewModel diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreen.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsScreen.kt similarity index 73% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreen.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsScreen.kt index f9b472eca7..e06d230c48 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreen.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsScreen.kt @@ -14,12 +14,12 @@ import app.k9mail.feature.account.common.ui.AccountTopAppBar import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.server.settings.R -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.ViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Effect +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.ViewModel @Composable -fun AccountOutgoingConfigScreen( +fun OutgoingServerSettingsScreen( onNext: () -> Unit, onBack: () -> Unit, viewModel: ViewModel, @@ -54,7 +54,7 @@ fun AccountOutgoingConfigScreen( }, modifier = modifier, ) { innerPadding -> - AccountOutgoingConfigContent( + OutgoingServerSettingsContent( state = state.value, onEvent = { dispatch(it) }, contentPadding = innerPadding, @@ -64,13 +64,13 @@ fun AccountOutgoingConfigScreen( @Composable @DevicePreviews -internal fun AccountOutgoingConfigScreenK9Preview() { +internal fun OutgoingServerSettingsScreenK9Preview() { K9Theme { - AccountOutgoingConfigScreen( + OutgoingServerSettingsScreen( onNext = {}, onBack = {}, - viewModel = AccountOutgoingConfigViewModel( - validator = AccountOutgoingConfigValidator(), + viewModel = OutgoingServerSettingsViewModel( + validator = OutgoingServerSettingsValidator(), accountStateRepository = PreviewAccountStateRepository(), ), ) @@ -79,13 +79,13 @@ internal fun AccountOutgoingConfigScreenK9Preview() { @Composable @DevicePreviews -internal fun AccountOutgoingConfigScreenThunderbirdPreview() { +internal fun OutgoingServerSettingsScreenThunderbirdPreview() { ThunderbirdTheme { - AccountOutgoingConfigScreen( + OutgoingServerSettingsScreen( onNext = {}, onBack = {}, - viewModel = AccountOutgoingConfigViewModel( - validator = AccountOutgoingConfigValidator(), + viewModel = OutgoingServerSettingsViewModel( + validator = OutgoingServerSettingsValidator(), accountStateRepository = PreviewAccountStateRepository(), ), ) diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateExtensions.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateExtensions.kt similarity index 50% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateExtensions.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateExtensions.kt index 945762c73e..5179c7c726 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateExtensions.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateExtensions.kt @@ -1,7 +1,7 @@ package app.k9mail.feature.account.server.settings.ui.outgoing -internal val AccountOutgoingConfigContract.State.isUsernameFieldVisible: Boolean +internal val OutgoingServerSettingsContract.State.isUsernameFieldVisible: Boolean get() = authenticationType.isUsernameRequired -internal val AccountOutgoingConfigContract.State.isPasswordFieldVisible: Boolean +internal val OutgoingServerSettingsContract.State.isPasswordFieldVisible: Boolean get() = authenticationType.isPasswordRequired diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt similarity index 95% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapper.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt index 18cbb2085f..02093ac83d 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapper.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt @@ -7,7 +7,7 @@ import app.k9mail.feature.account.common.domain.entity.toConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toMailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State import com.fsck.k9.mail.ServerSettings internal fun AccountState.toOutgoingConfigState(): State { diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigValidator.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsValidator.kt similarity index 92% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigValidator.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsValidator.kt index 951780d061..b0bf4ca460 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigValidator.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsValidator.kt @@ -6,12 +6,12 @@ import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePort import app.k9mail.feature.account.server.settings.domain.usecase.ValidateServer import app.k9mail.feature.account.server.settings.domain.usecase.ValidateUsername -internal class AccountOutgoingConfigValidator( +internal class OutgoingServerSettingsValidator( private val serverValidator: ValidateServer = ValidateServer(), private val portValidator: ValidatePort = ValidatePort(), private val usernameValidator: ValidateUsername = ValidateUsername(), private val passwordValidator: ValidatePassword = ValidatePassword(), -) : AccountOutgoingConfigContract.Validator { +) : OutgoingServerSettingsContract.Validator { override fun validateServer(server: String): ValidationResult { return serverValidator.execute(server) } diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt similarity index 86% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModel.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt index 6ece5c5d89..75a02f78bb 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModel.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt @@ -5,13 +5,13 @@ import app.k9mail.core.ui.compose.common.mvi.BaseViewModel import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Validator -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.ViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Effect +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Validator +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.ViewModel -class AccountOutgoingConfigViewModel( +class OutgoingServerSettingsViewModel( private val validator: Validator, private val accountStateRepository: AccountDomainContract.AccountStateRepository, initialState: State = State(), diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt deleted file mode 100644 index 55905a1128..0000000000 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigViewModel.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.k9mail.feature.account.server.settings.ui.outgoing.fake - -import app.k9mail.core.ui.compose.common.mvi.BaseViewModel -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.ViewModel - -class FakeAccountOutgoingConfigViewModel( - initialState: State = State(), -) : BaseViewModel(initialState), ViewModel { - - val events = mutableListOf() - - override fun event(event: Event) { - events.add(event) - } - - fun effect(effect: Effect) { - emitEffect(effect) - } -} diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeOutgoingServerSettingsValidator.kt similarity index 80% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeOutgoingServerSettingsValidator.kt index a1ebe20e84..0d9f7a2460 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeAccountOutgoingConfigValidator.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeOutgoingServerSettingsValidator.kt @@ -1,14 +1,14 @@ package app.k9mail.feature.account.server.settings.ui.outgoing.fake import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract -class FakeAccountOutgoingConfigValidator( +class FakeOutgoingServerSettingsValidator( private val serverAnswer: ValidationResult = ValidationResult.Success, private val portAnswer: ValidationResult = ValidationResult.Success, private val usernameAnswer: ValidationResult = ValidationResult.Success, private val passwordAnswer: ValidationResult = ValidationResult.Success, -) : AccountOutgoingConfigContract.Validator { +) : OutgoingServerSettingsContract.Validator { override fun validateServer(server: String): ValidationResult = serverAnswer override fun validatePort(port: Long?): ValidationResult = portAnswer override fun validateUsername(username: String): ValidationResult = usernameAnswer diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeOutgoingServerSettingsViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeOutgoingServerSettingsViewModel.kt new file mode 100644 index 0000000000..60c3feb127 --- /dev/null +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/fake/FakeOutgoingServerSettingsViewModel.kt @@ -0,0 +1,22 @@ +package app.k9mail.feature.account.server.settings.ui.outgoing.fake + +import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Effect +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.ViewModel + +class FakeOutgoingServerSettingsViewModel( + initialState: State = State(), +) : BaseViewModel(initialState), ViewModel { + + val events = mutableListOf() + + override fun event(event: Event) { + events.add(event) + } + + fun effect(effect: Effect) { + emitEffect(effect) + } +} diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsScreenKtTest.kt similarity index 72% rename from feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsScreenKtTest.kt index 52fe273f5f..a6237be505 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigScreenKtTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsScreenKtTest.kt @@ -2,25 +2,25 @@ package app.k9mail.feature.account.server.settings.ui.outgoing import app.k9mail.core.ui.compose.testing.ComposeTest import app.k9mail.core.ui.compose.testing.setContent -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Effect +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeOutgoingServerSettingsViewModel import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest import org.junit.Test -class AccountOutgoingConfigScreenKtTest : ComposeTest() { +class OutgoingServerSettingsScreenKtTest : ComposeTest() { @Test fun `should delegate navigation effects`() = runTest { val initialState = State() - val viewModel = FakeAccountOutgoingConfigViewModel(initialState) + val viewModel = FakeOutgoingServerSettingsViewModel(initialState) var onNextCounter = 0 var onBackCounter = 0 setContent { - AccountOutgoingConfigScreen( + OutgoingServerSettingsScreen( onNext = { onNextCounter++ }, onBack = { onBackCounter++ }, viewModel = viewModel, diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapperKtTest.kt similarity index 91% rename from feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapperKtTest.kt index 543229d92d..f657f33f4e 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateMapperKtTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapperKtTest.kt @@ -5,14 +5,14 @@ import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType import com.fsck.k9.mail.ServerSettings import org.junit.Test -class AccountOutgoingConfigStateMapperKtTest { +class OutgoingServerSettingsStateMapperKtTest { @Test fun `should map to server settings`() { diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateTest.kt similarity index 88% rename from feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateTest.kt index debee2e833..ade28a9679 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigStateTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateTest.kt @@ -5,12 +5,12 @@ import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State import assertk.assertThat import assertk.assertions.isEqualTo import org.junit.Test -class AccountOutgoingConfigStateTest { +class OutgoingServerSettingsStateTest { @Test fun `should set default values`() { diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModelTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt similarity index 94% rename from feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModelTest.kt rename to feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt index ee79d75f60..2907c3cf05 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/AccountOutgoingConfigViewModelTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt @@ -5,7 +5,6 @@ import app.k9mail.core.common.domain.usecase.validation.ValidationResult import app.k9mail.core.ui.compose.testing.MainDispatcherRule import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.eventStateTest -import app.k9mail.core.ui.compose.testing.mvi.turbines import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository import app.k9mail.feature.account.common.domain.AccountDomainContract @@ -16,10 +15,10 @@ import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity import app.k9mail.feature.account.common.domain.entity.toSmtpDefaultPort import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Effect -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.Event -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract.State -import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeAccountOutgoingConfigValidator +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Effect +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeOutgoingServerSettingsValidator import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType @@ -28,7 +27,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -class AccountOutgoingConfigViewModelTest { +class OutgoingServerSettingsViewModelTest { @get:Rule val mainDispatcherRule = MainDispatcherRule() @@ -256,7 +255,7 @@ class AccountOutgoingConfigViewModelTest { runTest { val initialState = State() val testSubject = createTestSubject( - validator = FakeAccountOutgoingConfigValidator( + validator = FakeOutgoingServerSettingsValidator( serverAnswer = ValidationResult.Failure(TestError), ), initialState = initialState, @@ -301,9 +300,9 @@ class AccountOutgoingConfigViewModelTest { private companion object { fun createTestSubject( initialState: State = State(), - validator: AccountOutgoingConfigContract.Validator = FakeAccountOutgoingConfigValidator(), + validator: OutgoingServerSettingsContract.Validator = FakeOutgoingServerSettingsValidator(), repository: AccountDomainContract.AccountStateRepository = InMemoryAccountStateRepository(), - ) = AccountOutgoingConfigViewModel( + ) = OutgoingServerSettingsViewModel( validator = validator, accountStateRepository = repository, initialState = initialState, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt index e6a76ee61f..3bc1b51268 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt @@ -6,9 +6,9 @@ import app.k9mail.core.ui.compose.common.mvi.observe import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsScreen import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsViewModel -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigScreen -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsScreen +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsViewModel import app.k9mail.feature.account.server.validation.KOIN_NAME_INCOMING_SERVER_VALIDATION import app.k9mail.feature.account.server.validation.KOIN_NAME_OUTGOING_SERVER_VALIDATION import app.k9mail.feature.account.server.validation.ui.ServerValidationContract @@ -38,7 +38,7 @@ fun AccountSetupScreen( incomingValidationViewModel: ServerValidationContract.ViewModel = koinViewModel( named(KOIN_NAME_INCOMING_SERVER_VALIDATION), ), - outgoingViewModel: AccountOutgoingConfigContract.ViewModel = koinViewModel(), + outgoingViewModel: OutgoingServerSettingsContract.ViewModel = koinViewModel(), outgoingValidationViewModel: ServerValidationContract.ViewModel = koinViewModel( named(KOIN_NAME_OUTGOING_SERVER_VALIDATION), ), @@ -83,7 +83,7 @@ fun AccountSetupScreen( } SetupStep.OUTGOING_CONFIG -> { - AccountOutgoingConfigScreen( + OutgoingServerSettingsScreen( onNext = { dispatch(Event.OnNext) }, onBack = { dispatch(Event.OnBack) }, viewModel = outgoingViewModel, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt index 92c23874aa..7aa4f6846e 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapper.kt @@ -6,7 +6,7 @@ import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract import app.k9mail.feature.account.setup.domain.entity.toAuthenticationType import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toIncomingProtocolType @@ -43,15 +43,15 @@ internal fun AccountAutoDiscoveryContract.State.toIncomingConfigState(): Incomin } } -internal fun AccountAutoDiscoveryContract.State.toOutgoingConfigState(): AccountOutgoingConfigContract.State { +internal fun AccountAutoDiscoveryContract.State.toOutgoingConfigState(): OutgoingServerSettingsContract.State { val outgoingSettings = autoDiscoverySettings?.outgoingServerSettings as? SmtpServerSettings? return if (outgoingSettings == null) { - AccountOutgoingConfigContract.State( + OutgoingServerSettingsContract.State( username = StringInputField(value = emailAddress.value), password = StringInputField(value = password.value), ) } else { - AccountOutgoingConfigContract.State( + OutgoingServerSettingsContract.State( server = StringInputField(value = outgoingSettings.hostname.value), security = outgoingSettings.connectionSecurity.toConnectionSecurity(), port = NumberInputField(value = outgoingSettings.port.value.toLong()), diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index c0a33084c6..c775657baa 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -6,7 +6,7 @@ import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract import app.k9mail.feature.account.server.validation.ui.ServerValidationContract import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult @@ -66,7 +66,7 @@ class AccountSetupModuleKtTest : KoinTest { AccountOAuthContract.State::class, ServerValidationContract.State::class, IncomingServerSettingsContract.State::class, - AccountOutgoingConfigContract.State::class, + OutgoingServerSettingsContract.State::class, AccountOptionsContract.State::class, AccountState::class, ServerCertificateErrorContract.State::class, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt index 7dc4f11668..3d1a16e828 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreenKtTest.kt @@ -5,7 +5,7 @@ import app.k9mail.core.ui.compose.testing.onNodeWithTag import app.k9mail.core.ui.compose.testing.setContent import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeIncomingServerSettingsViewModel -import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeAccountOutgoingConfigViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeOutgoingServerSettingsViewModel import app.k9mail.feature.account.server.validation.ui.fake.FakeServerValidationViewModel import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep @@ -32,7 +32,7 @@ class AccountSetupScreenKtTest : ComposeTest() { autoDiscoveryViewModel = FakeAccountAutoDiscoveryViewModel(), incomingViewModel = FakeIncomingServerSettingsViewModel(), incomingValidationViewModel = FakeServerValidationViewModel(), - outgoingViewModel = FakeAccountOutgoingConfigViewModel(), + outgoingViewModel = FakeOutgoingServerSettingsViewModel(), outgoingValidationViewModel = FakeServerValidationViewModel(), optionsViewModel = FakeAccountOptionsViewModel(), ) @@ -61,7 +61,7 @@ class AccountSetupScreenKtTest : ComposeTest() { autoDiscoveryViewModel = FakeAccountAutoDiscoveryViewModel(), incomingViewModel = FakeIncomingServerSettingsViewModel(), incomingValidationViewModel = FakeServerValidationViewModel(), - outgoingViewModel = FakeAccountOutgoingConfigViewModel(), + outgoingViewModel = FakeOutgoingServerSettingsViewModel(), outgoingValidationViewModel = FakeServerValidationViewModel(), optionsViewModel = FakeAccountOptionsViewModel(), ) @@ -86,7 +86,7 @@ class AccountSetupScreenKtTest : ComposeTest() { SetupStep.AUTO_CONFIG -> "AccountAutoDiscoveryContent" SetupStep.INCOMING_CONFIG -> "IncomingServerSettingsContent" SetupStep.INCOMING_VALIDATION -> "AccountValidationContent" - SetupStep.OUTGOING_CONFIG -> "AccountOutgoingConfigContent" + SetupStep.OUTGOING_CONFIG -> "OutgoingServerSettingsContent" SetupStep.OUTGOING_VALIDATION -> "AccountValidationContent" SetupStep.OPTIONS -> "AccountOptionsContent" } diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt index 076b9f3b9d..802cfe0e66 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryStateMapperKtTest.kt @@ -11,7 +11,7 @@ import app.k9mail.feature.account.common.domain.entity.IncomingProtocolType import app.k9mail.feature.account.common.domain.input.NumberInputField import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract -import app.k9mail.feature.account.server.settings.ui.outgoing.AccountOutgoingConfigContract +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryAuthenticationType import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity import app.k9mail.feature.account.setup.domain.entity.toConnectionSecurity @@ -94,7 +94,7 @@ class AccountAutoDiscoveryStateMapperKtTest { fun `should map to OutgoingConfigState when empty`() { val outgoingConfigState = EMPTY_STATE.toOutgoingConfigState() - assertThat(outgoingConfigState).isEqualTo(AccountOutgoingConfigContract.State()) + assertThat(outgoingConfigState).isEqualTo(OutgoingServerSettingsContract.State()) } @Test @@ -102,7 +102,7 @@ class AccountAutoDiscoveryStateMapperKtTest { val outgoingConfigState = EMAIL_PASSWORD_STATE.toOutgoingConfigState() assertThat(outgoingConfigState).isEqualTo( - AccountOutgoingConfigContract.State( + OutgoingServerSettingsContract.State( username = StringInputField(value = EMAIL_ADDRESS), password = StringInputField(value = PASSWORD), ), @@ -114,7 +114,7 @@ class AccountAutoDiscoveryStateMapperKtTest { val outgoingConfigState = AUTO_DISCOVERY_STATE.toOutgoingConfigState() assertThat(outgoingConfigState).isEqualTo( - AccountOutgoingConfigContract.State( + OutgoingServerSettingsContract.State( server = StringInputField(value = AUTO_DISCOVERY_HOSTNAME.value), security = AUTO_DISCOVERY_SECURITY.toConnectionSecurity(), port = NumberInputField(value = AUTO_DISCOVERY_PORT_SMTP.value.toLong()), @@ -130,7 +130,7 @@ class AccountAutoDiscoveryStateMapperKtTest { val outgoingConfigState = AUTO_DISCOVERY_STATE_USERNAME_EMPTY.toOutgoingConfigState() assertThat(outgoingConfigState).isEqualTo( - AccountOutgoingConfigContract.State( + OutgoingServerSettingsContract.State( server = StringInputField(value = AUTO_DISCOVERY_HOSTNAME.value), security = AUTO_DISCOVERY_SECURITY.toConnectionSecurity(), port = NumberInputField(value = AUTO_DISCOVERY_PORT_SMTP.value.toLong()), -- GitLab From 8d9747074b06d8f44c400ae5bf9cb56bd4a2ebaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 14:56:08 +0200 Subject: [PATCH 32/94] Change Gradle memory allowance to 3G --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4aaff1c8bc..414c015e0f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ android.useAndroidX=true android.enableJetifier=false android.nonTransitiveRClass=true -org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx3g -Dfile.encoding=UTF-8 org.gradle.parallel=true org.gradle.caching=true org.gradle.kotlin.dsl.allWarningsAsErrors=true -- GitLab From a71473fe1428f36278fde2625703505b21d89592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 14:56:08 +0200 Subject: [PATCH 33/94] Change Gradle memory allowance to 3G --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4aaff1c8bc..414c015e0f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ android.useAndroidX=true android.enableJetifier=false android.nonTransitiveRClass=true -org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx3g -Dfile.encoding=UTF-8 org.gradle.parallel=true org.gradle.caching=true org.gradle.kotlin.dsl.allWarningsAsErrors=true -- GitLab From 6a19427a8010f95749b5b5be4c94ba2a8112f419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 12 Sep 2023 17:08:19 +0200 Subject: [PATCH 34/94] Remove deprecation warning of `K9` class, as it's not true anymore and spamming the build output --- app/core/src/main/java/com/fsck/k9/K9.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/core/src/main/java/com/fsck/k9/K9.kt b/app/core/src/main/java/com/fsck/k9/K9.kt index 5951dc60f4..a6c13be7bd 100644 --- a/app/core/src/main/java/com/fsck/k9/K9.kt +++ b/app/core/src/main/java/com/fsck/k9/K9.kt @@ -13,7 +13,7 @@ import kotlinx.datetime.Clock import timber.log.Timber import timber.log.Timber.DebugTree -@Deprecated("Use GeneralSettingsManager and GeneralSettings instead") +// TODO "Use GeneralSettingsManager and GeneralSettings instead" object K9 : EarlyInit { private val generalSettingsManager: RealGeneralSettingsManager by inject() -- GitLab From 8019485750ed3b1de1d1e3fcae7ee176bb2f4f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 16:53:04 +0200 Subject: [PATCH 35/94] Move email validation to account setup --- .../domain/ServerSettingsDomainContract.kt | 4 ---- .../common/mapper/ValidationErrorStringMapper.kt | 14 -------------- .../settings/src/main/res/values/strings.xml | 2 -- .../feature/account/setup/domain/DomainContract.kt | 4 ++++ .../setup}/domain/usecase/ValidateEmailAddress.kt | 4 ++-- .../autodiscovery/AccountAutoDiscoveryValidator.kt | 4 ++-- .../ui/autodiscovery/AutoDiscoveryStringMapper.kt | 14 ++++++++++++++ .../account/setup/src/main/res/values/strings.xml | 3 +++ .../domain/usecase/ValidateEmailAddressTest.kt | 4 ++-- 9 files changed, 27 insertions(+), 26 deletions(-) rename feature/account/{server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings => setup/src/main/kotlin/app/k9mail/feature/account/setup}/domain/usecase/ValidateEmailAddress.kt (86%) rename feature/account/{server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings => setup/src/test/kotlin/app/k9mail/feature/account/setup}/domain/usecase/ValidateEmailAddressTest.kt (86%) diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerSettingsDomainContract.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerSettingsDomainContract.kt index 0bc312dcd8..7a9343b979 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerSettingsDomainContract.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/ServerSettingsDomainContract.kt @@ -6,10 +6,6 @@ interface ServerSettingsDomainContract { interface UseCase { - fun interface ValidateEmailAddress { - fun execute(emailAddress: String): ValidationResult - } - fun interface ValidatePassword { fun execute(password: String): ValidationResult } diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ValidationErrorStringMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ValidationErrorStringMapper.kt index 40a4f0f418..d196a4de1e 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ValidationErrorStringMapper.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/common/mapper/ValidationErrorStringMapper.kt @@ -3,7 +3,6 @@ package app.k9mail.feature.account.server.settings.ui.common.mapper import android.content.res.Resources import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.feature.account.server.settings.R -import app.k9mail.feature.account.server.settings.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError import app.k9mail.feature.account.server.settings.domain.usecase.ValidateImapPrefix.ValidateImapPrefixError import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePassword.ValidatePasswordError import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePort.ValidatePortError @@ -12,7 +11,6 @@ import app.k9mail.feature.account.server.settings.domain.usecase.ValidateUsernam fun ValidationError.toResourceString(resources: Resources): String { return when (this) { - is ValidateEmailAddressError -> toEmailAddressErrorString(resources) is ValidateServerError -> toServerErrorString(resources) is ValidatePortError -> toPortErrorString(resources) is ValidateUsernameError -> toUsernameErrorString(resources) @@ -22,18 +20,6 @@ fun ValidationError.toResourceString(resources: Resources): String { } } -private fun ValidateEmailAddressError.toEmailAddressErrorString(resources: Resources): String { - return when (this) { - is ValidateEmailAddressError.EmptyEmailAddress -> resources.getString( - R.string.account_server_settings_validation_error_email_address_required, - ) - - is ValidateEmailAddressError.InvalidEmailAddress -> resources.getString( - R.string.account_server_settings_validation_error_email_address_invalid, - ) - } -} - private fun ValidateServerError.toServerErrorString(resources: Resources): String { return when (this) { is ValidateServerError.EmptyServer -> resources.getString( diff --git a/feature/account/server/settings/src/main/res/values/strings.xml b/feature/account/server/settings/src/main/res/values/strings.xml index 4079537370..7b65001b2b 100644 --- a/feature/account/server/settings/src/main/res/values/strings.xml +++ b/feature/account/server/settings/src/main/res/values/strings.xml @@ -29,8 +29,6 @@ Outgoing server settings - Email address is required. - Email address is invalid. Server name is required. Port is required. Port is invalid (must be 1–65535). diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt index 1e49c57d79..66c7ff0f36 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/DomainContract.kt @@ -22,6 +22,10 @@ interface DomainContract { ): String } + fun interface ValidateEmailAddress { + fun execute(emailAddress: String): ValidationResult + } + fun interface ValidateConfigurationApproval { fun execute(isApproved: Boolean?, isAutoDiscoveryTrusted: Boolean?): ValidationResult } diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddress.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddress.kt similarity index 86% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddress.kt rename to feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddress.kt index 994348620f..3370de6bed 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddress.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddress.kt @@ -1,8 +1,8 @@ -package app.k9mail.feature.account.server.settings.domain.usecase +package app.k9mail.feature.account.setup.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.ServerSettingsDomainContract.UseCase +import app.k9mail.feature.account.setup.domain.DomainContract.UseCase class ValidateEmailAddress : UseCase.ValidateEmailAddress { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt index 8544218d5f..72dbeeab48 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryValidator.kt @@ -1,14 +1,14 @@ package app.k9mail.feature.account.setup.ui.autodiscovery import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.usecase.ValidateEmailAddress import app.k9mail.feature.account.server.settings.domain.usecase.ValidatePassword import app.k9mail.feature.account.setup.domain.DomainContract.UseCase import app.k9mail.feature.account.setup.domain.usecase.ValidateConfigurationApproval +import app.k9mail.feature.account.setup.domain.usecase.ValidateEmailAddress import app.k9mail.feature.account.server.settings.domain.ServerSettingsDomainContract.UseCase as ServerSettingsUseCase internal class AccountAutoDiscoveryValidator( - private val emailAddressValidator: ServerSettingsUseCase.ValidateEmailAddress = ValidateEmailAddress(), + private val emailAddressValidator: UseCase.ValidateEmailAddress = ValidateEmailAddress(), private val passwordValidator: ServerSettingsUseCase.ValidatePassword = ValidatePassword(), private val configurationApprovalValidator: UseCase.ValidateConfigurationApproval = ValidateConfigurationApproval(), ) : AccountAutoDiscoveryContract.Validator { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt index d942016e7f..9ec6756f5f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AutoDiscoveryStringMapper.kt @@ -5,6 +5,7 @@ import app.k9mail.core.common.domain.usecase.validation.ValidationError import app.k9mail.feature.account.setup.R import app.k9mail.feature.account.setup.domain.entity.AutoDiscoveryConnectionSecurity import app.k9mail.feature.account.setup.domain.usecase.ValidateConfigurationApproval +import app.k9mail.feature.account.setup.domain.usecase.ValidateEmailAddress internal fun AutoDiscoveryConnectionSecurity.toResourceString(resources: Resources): String { return when (this) { @@ -27,6 +28,7 @@ internal fun AccountAutoDiscoveryContract.Error.toResourceString(resources: Reso internal fun ValidationError.toResourceString(resources: Resources): String { return when (this) { + is ValidateEmailAddress.ValidateEmailAddressError -> toEmailAddressErrorString(resources) is ValidateConfigurationApproval.ValidateConfigurationApprovalError -> toConfigurationApprovalErrorString( resources, ) @@ -35,6 +37,18 @@ internal fun ValidationError.toResourceString(resources: Resources): String { } } +private fun ValidateEmailAddress.ValidateEmailAddressError.toEmailAddressErrorString(resources: Resources): String { + return when (this) { + is ValidateEmailAddress.ValidateEmailAddressError.EmptyEmailAddress -> resources.getString( + R.string.account_setup_auto_discovery_validation_error_email_address_required, + ) + + is ValidateEmailAddress.ValidateEmailAddressError.InvalidEmailAddress -> resources.getString( + R.string.account_setup_auto_discovery_validation_error_email_address_invalid, + ) + } +} + private fun ValidateConfigurationApproval.ValidateConfigurationApprovalError.toConfigurationApprovalErrorString( resources: Resources, ): String { diff --git a/feature/account/setup/src/main/res/values/strings.xml b/feature/account/setup/src/main/res/values/strings.xml index 9eaa60965e..557c9cd326 100644 --- a/feature/account/setup/src/main/res/values/strings.xml +++ b/feature/account/setup/src/main/res/values/strings.xml @@ -6,6 +6,9 @@ Network Unknown error + Email address is required. + Email address is invalid. + StartTLS SSL/TLS Finding email details diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddressTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddressTest.kt similarity index 86% rename from feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddressTest.kt rename to feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddressTest.kt index 225e6347bf..c00d35ed70 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/domain/usecase/ValidateEmailAddressTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/ValidateEmailAddressTest.kt @@ -1,7 +1,7 @@ -package app.k9mail.feature.account.server.settings.domain.usecase +package app.k9mail.feature.account.setup.domain.usecase import app.k9mail.core.common.domain.usecase.validation.ValidationResult -import app.k9mail.feature.account.server.settings.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError +import app.k9mail.feature.account.setup.domain.usecase.ValidateEmailAddress.ValidateEmailAddressError import assertk.assertThat import assertk.assertions.isInstanceOf import assertk.assertions.prop -- GitLab From 11b12f9c5eb8833bcaa324169f920e069c5336b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 18:10:51 +0200 Subject: [PATCH 36/94] Change named injection to typed injection for server validation to avoid issues with dependency resolution --- .../com/fsck/k9/DependencyInjectionTest.kt | 11 +-- .../validation/ServerValidationModule.kt | 17 ++--- ...el.kt => BaseServerValidationViewModel.kt} | 2 +- .../ui/IncomingServerValidationViewModel.kt | 25 +++++++ .../ui/OutgoingServerValidationViewModel.kt | 25 +++++++ .../validation/ui/ServerValidationContract.kt | 3 + .../ui/ServerValidationMainScreen.kt | 41 ++-------- .../FakeIncomingServerValidationViewModel.kt | 27 +++++++ .../FakeOutgoingServerValidationViewModel.kt | 27 +++++++ ...t => BaseServerValidationViewModelTest.kt} | 71 ++++++++++-------- .../IncomingServerValidationViewModelTest.kt | 75 +++++++++++++++++++ .../OutgoingServerValidationViewModelTest.kt | 75 +++++++++++++++++++ .../account/setup/ui/AccountSetupScreen.kt | 16 ++-- 13 files changed, 319 insertions(+), 96 deletions(-) rename feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/{ServerValidationViewModel.kt => BaseServerValidationViewModel.kt} (99%) create mode 100644 feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModel.kt create mode 100644 feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModel.kt create mode 100644 feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeIncomingServerValidationViewModel.kt create mode 100644 feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeOutgoingServerValidationViewModel.kt rename feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/{ServerValidationViewModelTest.kt => BaseServerValidationViewModelTest.kt} (81%) create mode 100644 feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModelTest.kt create mode 100644 feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModelTest.kt diff --git a/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt b/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt index 3593d9fbae..005a826bec 100644 --- a/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt +++ b/app/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt @@ -3,8 +3,6 @@ package com.fsck.k9 import android.view.ContextThemeWrapper import androidx.lifecycle.LifecycleOwner import androidx.work.WorkerParameters -import app.k9mail.feature.account.server.validation.KOIN_NAME_INCOMING_SERVER_VALIDATION -import app.k9mail.feature.account.server.validation.KOIN_NAME_OUTGOING_SERVER_VALIDATION import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract import app.k9mail.feature.account.server.validation.ui.ServerValidationContract import com.fsck.k9.account.AccountRemoverWorker @@ -23,7 +21,6 @@ import org.junit.runner.RunWith import org.koin.core.annotation.KoinInternalApi import org.koin.core.logger.PrintLogger import org.koin.core.parameter.parametersOf -import org.koin.core.qualifier.named import org.koin.java.KoinJavaComponent import org.koin.test.AutoCloseKoinTest import org.koin.test.check.checkModules @@ -61,12 +58,8 @@ class DependencyInjectionTest : AutoCloseKoinTest() { withParameters(clazz = Class.forName("com.fsck.k9.view.K9WebViewClient").kotlin) { parametersOf(null, null) } - withParameter( - named(KOIN_NAME_INCOMING_SERVER_VALIDATION), - ) { authStateStorage } - withParameter( - named(KOIN_NAME_OUTGOING_SERVER_VALIDATION), - ) { authStateStorage } + withParameter { authStateStorage } + withParameter { authStateStorage } withParameter { authStateStorage } withParameter { mock() } } diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt index 6c9bc29e70..35f61cda13 100644 --- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt @@ -6,12 +6,12 @@ import app.k9mail.feature.account.oauth.featureAccountOAuthModule import app.k9mail.feature.account.server.certificate.featureAccountServerCertificateModule import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract import app.k9mail.feature.account.server.validation.domain.usecase.ValidateServerSettings -import app.k9mail.feature.account.server.validation.ui.ServerValidationViewModel +import app.k9mail.feature.account.server.validation.ui.IncomingServerValidationViewModel +import app.k9mail.feature.account.server.validation.ui.OutgoingServerValidationViewModel import com.fsck.k9.mail.store.imap.ImapServerSettingsValidator import com.fsck.k9.mail.store.pop3.Pop3ServerSettingsValidator import com.fsck.k9.mail.transport.smtp.SmtpServerSettingsValidator import org.koin.androidx.viewmodel.dsl.viewModel -import org.koin.core.qualifier.named import org.koin.dsl.module val featureAccountServerValidationModule = module { @@ -40,28 +40,23 @@ val featureAccountServerValidationModule = module { ) } - viewModel(named(KOIN_NAME_INCOMING_SERVER_VALIDATION)) { - ServerValidationViewModel( + viewModel { + IncomingServerValidationViewModel( validateServerSettings = get(), accountStateRepository = get(), authorizationStateRepository = get(), certificateErrorRepository = get(), oAuthViewModel = get(), - isIncomingValidation = true, ) } - viewModel(named(KOIN_NAME_OUTGOING_SERVER_VALIDATION)) { - ServerValidationViewModel( + viewModel { + OutgoingServerValidationViewModel( validateServerSettings = get(), accountStateRepository = get(), authorizationStateRepository = get(), certificateErrorRepository = get(), oAuthViewModel = get(), - isIncomingValidation = false, ) } } - -const val KOIN_NAME_INCOMING_SERVER_VALIDATION = "incoming_server_validation" -const val KOIN_NAME_OUTGOING_SERVER_VALIDATION = "outgoing_server_validation" diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/BaseServerValidationViewModel.kt similarity index 99% rename from feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt rename to feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/BaseServerValidationViewModel.kt index bdd457c3ef..acb629f66f 100644 --- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModel.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/BaseServerValidationViewModel.kt @@ -22,7 +22,7 @@ import kotlinx.coroutines.launch private const val CONTINUE_NEXT_DELAY = 2000L @Suppress("TooManyFunctions") -class ServerValidationViewModel( +abstract class BaseServerValidationViewModel( private val accountStateRepository: AccountDomainContract.AccountStateRepository, private val validateServerSettings: ServerValidationDomainContract.UseCase.ValidateServerSettings, private val authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModel.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModel.kt new file mode 100644 index 0000000000..dcef4fc748 --- /dev/null +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModel.kt @@ -0,0 +1,25 @@ +package app.k9mail.feature.account.server.validation.ui + +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract +import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract +import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract.UseCase + +class IncomingServerValidationViewModel( + accountStateRepository: AccountDomainContract.AccountStateRepository, + validateServerSettings: UseCase.ValidateServerSettings, + authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, + certificateErrorRepository: ServerCertificateDomainContract.ServerCertificateErrorRepository, + oAuthViewModel: AccountOAuthContract.ViewModel, + initialState: ServerValidationContract.State? = null, +) : BaseServerValidationViewModel( + accountStateRepository = accountStateRepository, + validateServerSettings = validateServerSettings, + authorizationStateRepository = authorizationStateRepository, + certificateErrorRepository = certificateErrorRepository, + oAuthViewModel = oAuthViewModel, + initialState = initialState, + isIncomingValidation = true, +), + ServerValidationContract.IncomingViewModel diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModel.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModel.kt new file mode 100644 index 0000000000..da1d13db88 --- /dev/null +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModel.kt @@ -0,0 +1,25 @@ +package app.k9mail.feature.account.server.validation.ui + +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract +import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract +import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract.UseCase + +class OutgoingServerValidationViewModel( + accountStateRepository: AccountDomainContract.AccountStateRepository, + validateServerSettings: UseCase.ValidateServerSettings, + authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, + certificateErrorRepository: ServerCertificateDomainContract.ServerCertificateErrorRepository, + oAuthViewModel: AccountOAuthContract.ViewModel, + initialState: ServerValidationContract.State? = null, +) : BaseServerValidationViewModel( + accountStateRepository = accountStateRepository, + validateServerSettings = validateServerSettings, + authorizationStateRepository = authorizationStateRepository, + certificateErrorRepository = certificateErrorRepository, + oAuthViewModel = oAuthViewModel, + initialState = initialState, + isIncomingValidation = false, +), + ServerValidationContract.OutgoingViewModel diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContract.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContract.kt index 083f4a606e..a4555c6f35 100644 --- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContract.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationContract.kt @@ -14,6 +14,9 @@ interface ServerValidationContract { val oAuthViewModel: AccountOAuthContract.ViewModel } + interface OutgoingViewModel : ViewModel + interface IncomingViewModel : ViewModel + data class State( val emailAddress: String? = null, val serverSettings: ServerSettings? = null, diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt index 0d1db380f8..8b138e0255 100644 --- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt @@ -10,12 +10,11 @@ import app.k9mail.core.ui.compose.theme.ThunderbirdTheme import app.k9mail.feature.account.common.ui.AppTitleTopHeader import app.k9mail.feature.account.common.ui.WizardNavigationBar import app.k9mail.feature.account.common.ui.WizardNavigationBarState -import app.k9mail.feature.account.common.ui.preview.PreviewAccountStateRepository import app.k9mail.feature.account.oauth.ui.preview.PreviewAccountOAuthViewModel -import app.k9mail.feature.account.server.certificate.data.InMemoryServerCertificateErrorRepository import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.ViewModel -import com.fsck.k9.mail.server.ServerSettingsValidationResult +import app.k9mail.feature.account.server.validation.ui.fake.FakeIncomingServerValidationViewModel +import app.k9mail.feature.account.server.validation.ui.fake.FakeOutgoingServerValidationViewModel @Composable internal fun ServerValidationMainScreen( @@ -55,15 +54,8 @@ internal fun ServerValidationMainScreen( internal fun IncomingServerValidationScreenK9Preview() { K9Theme { ServerValidationMainScreen( - viewModel = ServerValidationViewModel( - validateServerSettings = { - ServerSettingsValidationResult.Success - }, - accountStateRepository = PreviewAccountStateRepository(), - authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryServerCertificateErrorRepository(), + viewModel = FakeIncomingServerValidationViewModel( oAuthViewModel = PreviewAccountOAuthViewModel(), - isIncomingValidation = true, ), ) } @@ -74,15 +66,8 @@ internal fun IncomingServerValidationScreenK9Preview() { internal fun IncomingServerValidationScreenThunderbirdPreview() { ThunderbirdTheme { ServerValidationMainScreen( - viewModel = ServerValidationViewModel( - validateServerSettings = { - ServerSettingsValidationResult.Success - }, - accountStateRepository = PreviewAccountStateRepository(), - authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryServerCertificateErrorRepository(), + viewModel = FakeIncomingServerValidationViewModel( oAuthViewModel = PreviewAccountOAuthViewModel(), - isIncomingValidation = true, ), ) } @@ -93,15 +78,8 @@ internal fun IncomingServerValidationScreenThunderbirdPreview() { internal fun AccountOutgoingValidationScreenK9Preview() { K9Theme { ServerValidationMainScreen( - viewModel = ServerValidationViewModel( - validateServerSettings = { - ServerSettingsValidationResult.Success - }, - accountStateRepository = PreviewAccountStateRepository(), - authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryServerCertificateErrorRepository(), + viewModel = FakeOutgoingServerValidationViewModel( oAuthViewModel = PreviewAccountOAuthViewModel(), - isIncomingValidation = false, ), ) } @@ -112,15 +90,8 @@ internal fun AccountOutgoingValidationScreenK9Preview() { internal fun AccountOutgoingValidationScreenThunderbirdPreview() { ThunderbirdTheme { ServerValidationMainScreen( - viewModel = ServerValidationViewModel( - validateServerSettings = { - ServerSettingsValidationResult.Success - }, - accountStateRepository = PreviewAccountStateRepository(), - authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryServerCertificateErrorRepository(), + viewModel = FakeOutgoingServerValidationViewModel( oAuthViewModel = PreviewAccountOAuthViewModel(), - isIncomingValidation = false, ), ) } diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeIncomingServerValidationViewModel.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeIncomingServerValidationViewModel.kt new file mode 100644 index 0000000000..38b7fbefe8 --- /dev/null +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeIncomingServerValidationViewModel.kt @@ -0,0 +1,27 @@ +package app.k9mail.feature.account.server.validation.ui.fake + +import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.ViewModel + +class FakeIncomingServerValidationViewModel( + override val oAuthViewModel: AccountOAuthContract.ViewModel = FakeAccountOAuthViewModel(), + override val isIncomingValidation: Boolean = true, + initialState: State = State(), +) : BaseViewModel(initialState), ServerValidationContract.IncomingViewModel { + + val events = mutableListOf() + + override fun event(event: Event) { + events.add(event) + } + + fun effect(effect: Effect) { + emitEffect(effect) + } +} diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeOutgoingServerValidationViewModel.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeOutgoingServerValidationViewModel.kt new file mode 100644 index 0000000000..3b82517c18 --- /dev/null +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/fake/FakeOutgoingServerValidationViewModel.kt @@ -0,0 +1,27 @@ +package app.k9mail.feature.account.server.validation.ui.fake + +import app.k9mail.core.ui.compose.common.mvi.BaseViewModel +import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.ViewModel + +class FakeOutgoingServerValidationViewModel( + override val oAuthViewModel: AccountOAuthContract.ViewModel = FakeAccountOAuthViewModel(), + override val isIncomingValidation: Boolean = true, + initialState: State = State(), +) : BaseViewModel(initialState), ServerValidationContract.OutgoingViewModel { + + val events = mutableListOf() + + override fun event(event: Event) { + events.add(event) + } + + fun effect(effect: Effect) { + emitEffect(effect) + } +} diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/BaseServerValidationViewModelTest.kt similarity index 81% rename from feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt rename to feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/BaseServerValidationViewModelTest.kt index a482fdf65d..af0f8b03d1 100644 --- a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationViewModelTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/BaseServerValidationViewModelTest.kt @@ -4,9 +4,14 @@ import app.k9mail.core.ui.compose.testing.MainDispatcherRule import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract +import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel import app.k9mail.feature.account.server.certificate.data.InMemoryServerCertificateErrorRepository +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract +import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Effect import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Error import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Event @@ -23,16 +28,22 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -class ServerValidationViewModelTest { +abstract class BaseServerValidationViewModelTest { @get:Rule val mainDispatcherRule = MainDispatcherRule() @Test fun `should update state when LoadAccountStateAndValidate event received and validate`() = runTest { - val accountState = AccountState( - incomingServerSettings = IMAP_SERVER_SETTINGS, - ) + val accountState = if (isIncomingValidation) { + AccountState( + incomingServerSettings = SERVER_SETTINGS, + ) + } else { + AccountState( + outgoingServerSettings = SERVER_SETTINGS, + ) + } val initialState = State( serverSettings = null, isLoading = true, @@ -47,7 +58,7 @@ class ServerValidationViewModelTest { val turbines = turbinesWithInitialStateCheck(testSubject, initialState) val expectedState = State( - serverSettings = IMAP_SERVER_SETTINGS, + serverSettings = SERVER_SETTINGS, isLoading = false, error = null, isSuccess = false, @@ -93,7 +104,7 @@ class ServerValidationViewModelTest { @Test fun `should validate server settings when ValidateServerSettings event received`() = runTest { val initialState = State( - serverSettings = IMAP_SERVER_SETTINGS, + serverSettings = SERVER_SETTINGS, ) val testSubject = createTestSubject( serverSettingsValidationResult = ServerSettingsValidationResult.Success, @@ -123,7 +134,7 @@ class ServerValidationViewModelTest { @Test fun `should set error state when ValidateServerSettings received and check settings failed`() = runTest { val initialState = State( - serverSettings = IMAP_SERVER_SETTINGS, + serverSettings = SERVER_SETTINGS, ) val testSubject = createTestSubject( serverSettingsValidationResult = ServerSettingsValidationResult.ServerError("server error"), @@ -151,7 +162,7 @@ class ServerValidationViewModelTest { @Test fun `should emit effect NavigateNext when ValidateConfig is successful`() = runTest { val initialState = State( - serverSettings = IMAP_SERVER_SETTINGS, + serverSettings = SERVER_SETTINGS, isSuccess = true, ) val testSubject = createTestSubject( @@ -187,11 +198,12 @@ class ServerValidationViewModelTest { @Test fun `should clear error and trigger check settings when OnRetryClicked event received`() = runTest { val initialState = State( - serverSettings = IMAP_SERVER_SETTINGS, + serverSettings = SERVER_SETTINGS, error = Error.ServerError("server error"), ) var checkSettingsCalled = false - val testSubject = ServerValidationViewModel( + + val testSubject = createTestSubject( validateServerSettings = { delay(50) checkSettingsCalled = true @@ -225,26 +237,25 @@ class ServerValidationViewModelTest { } } - private companion object { - fun createTestSubject( - serverSettingsValidationResult: ServerSettingsValidationResult = ServerSettingsValidationResult.Success, - accountState: AccountState = AccountState(), - initialState: State = State(), - ): ServerValidationViewModel { - return ServerValidationViewModel( - validateServerSettings = { - delay(50) - serverSettingsValidationResult - }, - accountStateRepository = InMemoryAccountStateRepository(accountState), - authorizationStateRepository = { true }, - certificateErrorRepository = InMemoryServerCertificateErrorRepository(), - oAuthViewModel = FakeAccountOAuthViewModel(), - initialState = initialState, - ) - } - - val IMAP_SERVER_SETTINGS = ServerSettings( + abstract fun createTestSubject( + serverSettingsValidationResult: ServerSettingsValidationResult = ServerSettingsValidationResult.Success, + accountState: AccountState = AccountState(), + initialState: State = State(), + ): T + + abstract fun createTestSubject( + accountStateRepository: AccountDomainContract.AccountStateRepository, + validateServerSettings: ServerValidationDomainContract.UseCase.ValidateServerSettings, + authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, + certificateErrorRepository: ServerCertificateDomainContract.ServerCertificateErrorRepository, + oAuthViewModel: AccountOAuthContract.ViewModel, + initialState: State, + ): T + + abstract val isIncomingValidation: Boolean + + protected companion object { + val SERVER_SETTINGS = ServerSettings( type = "imap", host = "imap.example.com", port = 465, diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModelTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModelTest.kt new file mode 100644 index 0000000000..51b150e295 --- /dev/null +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModelTest.kt @@ -0,0 +1,75 @@ +package app.k9mail.feature.account.server.validation.ui + +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract +import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel +import app.k9mail.feature.account.server.certificate.data.InMemoryServerCertificateErrorRepository +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract +import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Error +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State +import assertk.assertThat +import assertk.assertions.isTrue +import com.fsck.k9.mail.server.ServerSettingsValidationResult +import kotlinx.coroutines.delay +import org.junit.Test + +class IncomingServerValidationViewModelTest : BaseServerValidationViewModelTest() { + + @Test + fun `should set isIncoming to true`() { + val testSubject = createTestSubject( + serverSettingsValidationResult = ServerSettingsValidationResult.Success, + accountState = AccountState( + incomingServerSettings = SERVER_SETTINGS, + ), + initialState = State( + serverSettings = null, + isLoading = true, + error = Error.ServerError("server error"), + isSuccess = true, + ), + ) + + assertThat(testSubject.isIncomingValidation).isTrue() + } + + override fun createTestSubject( + serverSettingsValidationResult: ServerSettingsValidationResult, + accountState: AccountState, + initialState: State, + ): IncomingServerValidationViewModel { + return IncomingServerValidationViewModel( + validateServerSettings = { + delay(50) + serverSettingsValidationResult + }, + accountStateRepository = InMemoryAccountStateRepository(accountState), + authorizationStateRepository = { true }, + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), + oAuthViewModel = FakeAccountOAuthViewModel(), + initialState = initialState, + ) + } + + override fun createTestSubject( + accountStateRepository: AccountDomainContract.AccountStateRepository, + validateServerSettings: ServerValidationDomainContract.UseCase.ValidateServerSettings, + authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, + certificateErrorRepository: ServerCertificateDomainContract.ServerCertificateErrorRepository, + oAuthViewModel: AccountOAuthContract.ViewModel, + initialState: State, + ) = IncomingServerValidationViewModel( + accountStateRepository = accountStateRepository, + validateServerSettings = validateServerSettings, + authorizationStateRepository = authorizationStateRepository, + certificateErrorRepository = certificateErrorRepository, + oAuthViewModel = oAuthViewModel, + initialState = initialState, + ) + + override val isIncomingValidation: Boolean = true +} diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModelTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModelTest.kt new file mode 100644 index 0000000000..068fbf43f3 --- /dev/null +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModelTest.kt @@ -0,0 +1,75 @@ +package app.k9mail.feature.account.server.validation.ui + +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.oauth.domain.AccountOAuthDomainContract +import app.k9mail.feature.account.oauth.ui.AccountOAuthContract +import app.k9mail.feature.account.oauth.ui.fake.FakeAccountOAuthViewModel +import app.k9mail.feature.account.server.certificate.data.InMemoryServerCertificateErrorRepository +import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract +import app.k9mail.feature.account.server.validation.domain.ServerValidationDomainContract +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.Error +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract.State +import assertk.assertThat +import assertk.assertions.isFalse +import com.fsck.k9.mail.server.ServerSettingsValidationResult +import kotlinx.coroutines.delay +import org.junit.Test + +class OutgoingServerValidationViewModelTest : BaseServerValidationViewModelTest() { + + @Test + fun `should set isIncoming to false`() { + val testSubject = createTestSubject( + serverSettingsValidationResult = ServerSettingsValidationResult.Success, + accountState = AccountState( + outgoingServerSettings = SERVER_SETTINGS, + ), + initialState = State( + serverSettings = null, + isLoading = true, + error = Error.ServerError("server error"), + isSuccess = true, + ), + ) + + assertThat(testSubject.isIncomingValidation).isFalse() + } + + override fun createTestSubject( + serverSettingsValidationResult: ServerSettingsValidationResult, + accountState: AccountState, + initialState: State, + ): OutgoingServerValidationViewModel { + return OutgoingServerValidationViewModel( + validateServerSettings = { + delay(50) + serverSettingsValidationResult + }, + accountStateRepository = InMemoryAccountStateRepository(accountState), + authorizationStateRepository = { true }, + certificateErrorRepository = InMemoryServerCertificateErrorRepository(), + oAuthViewModel = FakeAccountOAuthViewModel(), + initialState = initialState, + ) + } + + override fun createTestSubject( + accountStateRepository: AccountDomainContract.AccountStateRepository, + validateServerSettings: ServerValidationDomainContract.UseCase.ValidateServerSettings, + authorizationStateRepository: AccountOAuthDomainContract.AuthorizationStateRepository, + certificateErrorRepository: ServerCertificateDomainContract.ServerCertificateErrorRepository, + oAuthViewModel: AccountOAuthContract.ViewModel, + initialState: State, + ) = OutgoingServerValidationViewModel( + accountStateRepository = accountStateRepository, + validateServerSettings = validateServerSettings, + authorizationStateRepository = authorizationStateRepository, + certificateErrorRepository = certificateErrorRepository, + oAuthViewModel = oAuthViewModel, + initialState = initialState, + ) + + override val isIncomingValidation: Boolean = false +} diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt index 3bc1b51268..98b96ce9ac 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupScreen.kt @@ -9,11 +9,10 @@ import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSett import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsScreen import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsViewModel -import app.k9mail.feature.account.server.validation.KOIN_NAME_INCOMING_SERVER_VALIDATION -import app.k9mail.feature.account.server.validation.KOIN_NAME_OUTGOING_SERVER_VALIDATION +import app.k9mail.feature.account.server.validation.ui.IncomingServerValidationViewModel +import app.k9mail.feature.account.server.validation.ui.OutgoingServerValidationViewModel import app.k9mail.feature.account.server.validation.ui.ServerValidationContract import app.k9mail.feature.account.server.validation.ui.ServerValidationScreen -import app.k9mail.feature.account.server.validation.ui.ServerValidationViewModel import app.k9mail.feature.account.setup.ui.AccountSetupContract.Effect import app.k9mail.feature.account.setup.ui.AccountSetupContract.Event import app.k9mail.feature.account.setup.ui.AccountSetupContract.SetupStep @@ -25,7 +24,6 @@ import app.k9mail.feature.account.setup.ui.options.AccountOptionsContract import app.k9mail.feature.account.setup.ui.options.AccountOptionsScreen import app.k9mail.feature.account.setup.ui.options.AccountOptionsViewModel import org.koin.androidx.compose.koinViewModel -import org.koin.core.qualifier.named @Suppress("LongMethod") @Composable @@ -35,13 +33,11 @@ fun AccountSetupScreen( viewModel: ViewModel = koinViewModel(), autoDiscoveryViewModel: AccountAutoDiscoveryContract.ViewModel = koinViewModel(), incomingViewModel: IncomingServerSettingsContract.ViewModel = koinViewModel(), - incomingValidationViewModel: ServerValidationContract.ViewModel = koinViewModel( - named(KOIN_NAME_INCOMING_SERVER_VALIDATION), - ), + incomingValidationViewModel: ServerValidationContract.ViewModel = + koinViewModel(), outgoingViewModel: OutgoingServerSettingsContract.ViewModel = koinViewModel(), - outgoingValidationViewModel: ServerValidationContract.ViewModel = koinViewModel( - named(KOIN_NAME_OUTGOING_SERVER_VALIDATION), - ), + outgoingValidationViewModel: ServerValidationContract.ViewModel = + koinViewModel(), optionsViewModel: AccountOptionsContract.ViewModel = koinViewModel(), ) { val (state, dispatch) = viewModel.observe { effect -> -- GitLab From 25accaf905225db924d1f346bb2f7a180dcde7a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 17:46:07 +0200 Subject: [PATCH 37/94] Add observeWithoutEffect method --- .../common/mvi/UnidirectionalViewModel.kt | 42 +++++++++++++++++++ .../ui/ServerValidationMainScreen.kt | 5 +-- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/mvi/UnidirectionalViewModel.kt b/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/mvi/UnidirectionalViewModel.kt index f79840deff..de46e8f291 100644 --- a/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/mvi/UnidirectionalViewModel.kt +++ b/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/mvi/UnidirectionalViewModel.kt @@ -102,3 +102,45 @@ inline fun UnidirectionalViewModel, + * onNavigateNext: () -> Unit, + * onNavigateBack: () -> Unit, + * ) { + * val (state, dispatch) = viewModel.observeWithoutEffect() + * + * MyContent( + * onNextClick = { + * dispatch(MyEvent.OnNext) + * }, + * onBackClick = { + * dispatch(MyEvent.OnBack) + * }, + * state = state.value, + * ) + * } + * ``` + * + * @param STATE The type that represents the state of the ViewModel. + * @param EVENT The type that represents user actions that can occur and should be handled by the ViewModel. + * + * @return A [StateDispatch] containing the state and a dispatch function. + */ +@Composable +inline fun UnidirectionalViewModel + .observeWithoutEffect(): StateDispatch { + val collectedState = state.collectAsStateWithLifecycle() + val dispatch: (EVENT) -> Unit = { event(it) } + + return StateDispatch( + state = collectedState, + dispatch = dispatch, + ) +} diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt index 8b138e0255..419e24a7ea 100644 --- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/ServerValidationMainScreen.kt @@ -2,8 +2,8 @@ package app.k9mail.feature.account.server.validation.ui import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.lifecycle.compose.collectAsStateWithLifecycle import app.k9mail.core.ui.compose.common.DevicePreviews +import app.k9mail.core.ui.compose.common.mvi.observeWithoutEffect import app.k9mail.core.ui.compose.designsystem.template.Scaffold import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme @@ -21,8 +21,7 @@ internal fun ServerValidationMainScreen( viewModel: ViewModel, modifier: Modifier = Modifier, ) { - val state = viewModel.state.collectAsStateWithLifecycle() - val dispatch = { event: Event -> viewModel.event(event) } + val (state, dispatch) = viewModel.observeWithoutEffect() Scaffold( topBar = { -- GitLab From 1e6eaae18e403227e806aecf93c64a53ee74d36b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Thu, 14 Sep 2023 10:54:57 +0200 Subject: [PATCH 38/94] Fix Out of Memory and Gradle daemon disappeared issues, also improves build speed --- gradle.properties | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 414c015e0f..2f19a6b1a8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,9 @@ android.useAndroidX=true android.enableJetifier=false android.nonTransitiveRClass=true -org.gradle.jvmargs=-Xmx3g -Dfile.encoding=UTF-8 +## Ensure important default jvmargs aren't overwritten. See https://github.com/gradle/gradle/issues/19750 +org.gradle.jvmargs=-Xmx4G -Xms1G -XX:MaxMetaspaceSize=1536M -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError + org.gradle.parallel=true org.gradle.caching=true org.gradle.kotlin.dsl.allWarningsAsErrors=true -- GitLab From cea52fca9eb487894923ef77abbb1c3c1956293d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Thu, 14 Sep 2023 10:55:39 +0200 Subject: [PATCH 39/94] Enable Gradle configuration cache --- gradle.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gradle.properties b/gradle.properties index 2f19a6b1a8..e4d1f1ce48 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,13 @@ android.useAndroidX=true android.enableJetifier=false android.nonTransitiveRClass=true +# Gradle ## Ensure important default jvmargs aren't overwritten. See https://github.com/gradle/gradle/issues/19750 org.gradle.jvmargs=-Xmx4G -Xms1G -XX:MaxMetaspaceSize=1536M -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError org.gradle.parallel=true + org.gradle.caching=true +org.gradle.configuration-cache=true + org.gradle.kotlin.dsl.allWarningsAsErrors=true -- GitLab From 57580f2cb7582a4d80e0793f2bfc4b287ee555d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Thu, 14 Sep 2023 10:55:50 +0200 Subject: [PATCH 40/94] Cleanup --- gradle.properties | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gradle.properties b/gradle.properties index e4d1f1ce48..d90d2679b5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,14 +1,15 @@ -# Disable buildFeatures flags by default +# Android +android.useAndroidX=true +android.enableJetifier=false +android.nonTransitiveRClass=true + +## Disable buildFeatures flags by default android.defaults.buildfeatures.aidl=false android.defaults.buildfeatures.buildconfig=false android.defaults.buildfeatures.renderscript=false android.defaults.buildfeatures.resvalues=false android.defaults.buildfeatures.shaders=false -android.useAndroidX=true -android.enableJetifier=false -android.nonTransitiveRClass=true - # Gradle ## Ensure important default jvmargs aren't overwritten. See https://github.com/gradle/gradle/issues/19750 org.gradle.jvmargs=-Xmx4G -Xms1G -XX:MaxMetaspaceSize=1536M -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError -- GitLab From 72de4c6b67b0cdeb639445e18b0df672da2abe59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Thu, 14 Sep 2023 14:57:03 +0200 Subject: [PATCH 41/94] Suppress error about line length --- .../core/ui/compose/common/mvi/UnidirectionalViewModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/mvi/UnidirectionalViewModel.kt b/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/mvi/UnidirectionalViewModel.kt index de46e8f291..fb8f9685ad 100644 --- a/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/mvi/UnidirectionalViewModel.kt +++ b/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/mvi/UnidirectionalViewModel.kt @@ -133,9 +133,9 @@ inline fun UnidirectionalViewModel UnidirectionalViewModel - .observeWithoutEffect(): StateDispatch { +inline fun UnidirectionalViewModel.observeWithoutEffect(): StateDispatch { val collectedState = state.collectAsStateWithLifecycle() val dispatch: (EVENT) -> Unit = { event(it) } -- GitLab From a7ca61883c4f7a2efdfecf7d5da0f25cefdda740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Fri, 15 Sep 2023 11:03:58 +0200 Subject: [PATCH 42/94] Add account uuid --- .../k9mail/feature/account/common/domain/entity/Account.kt | 1 + .../feature/account/common/domain/entity/AccountState.kt | 1 + .../common/data/InMemoryAccountStateRepositoryTest.kt | 5 +++++ .../feature/account/setup/domain/usecase/CreateAccount.kt | 3 +++ .../account/setup/domain/usecase/CreateAccountTest.kt | 2 ++ 5 files changed, 12 insertions(+) diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/Account.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/Account.kt index a5f0c7fe97..9fed2db7b7 100644 --- a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/Account.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/Account.kt @@ -3,6 +3,7 @@ package app.k9mail.feature.account.common.domain.entity import com.fsck.k9.mail.ServerSettings data class Account( + val uuid: String, val emailAddress: String, val incomingServerSettings: ServerSettings, val outgoingServerSettings: ServerSettings, diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountState.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountState.kt index b683854de3..ae10bd2f3a 100644 --- a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountState.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/entity/AccountState.kt @@ -3,6 +3,7 @@ package app.k9mail.feature.account.common.domain.entity import com.fsck.k9.mail.ServerSettings data class AccountState( + val uuid: String? = null, val emailAddress: String? = null, val incomingServerSettings: ServerSettings? = null, val outgoingServerSettings: ServerSettings? = null, diff --git a/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt index 3628d45ef0..0e22332bfb 100644 --- a/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt +++ b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt @@ -20,6 +20,7 @@ class InMemoryAccountStateRepositoryTest { assertThat(result).isEqualTo( AccountState( + uuid = null, emailAddress = null, incomingServerSettings = null, outgoingServerSettings = null, @@ -33,6 +34,7 @@ class InMemoryAccountStateRepositoryTest { fun `should save state`() { val testSubject = InMemoryAccountStateRepository( AccountState( + uuid = "uuid", emailAddress = "emailAddress", incomingServerSettings = INCOMING_SERVER_SETTINGS, outgoingServerSettings = OUTGOING_SERVER_SETTINGS, @@ -41,6 +43,7 @@ class InMemoryAccountStateRepositoryTest { ), ) val newState = AccountState( + uuid = "uuid2", emailAddress = "emailAddress2", incomingServerSettings = INCOMING_SERVER_SETTINGS.copy(host = "imap2.example.org"), outgoingServerSettings = OUTGOING_SERVER_SETTINGS.copy(host = "smtp2.example.org"), @@ -114,6 +117,7 @@ class InMemoryAccountStateRepositoryTest { fun `should clear state`() { val testSubject = InMemoryAccountStateRepository( AccountState( + uuid = "uuid", emailAddress = "emailAddress", incomingServerSettings = INCOMING_SERVER_SETTINGS, outgoingServerSettings = OUTGOING_SERVER_SETTINGS, @@ -126,6 +130,7 @@ class InMemoryAccountStateRepositoryTest { assertThat(testSubject.getState()).isEqualTo( AccountState( + uuid = null, emailAddress = null, incomingServerSettings = null, outgoingServerSettings = null, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccount.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccount.kt index a9a199278f..392ee058fd 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccount.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccount.kt @@ -6,9 +6,11 @@ import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCrea import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult import app.k9mail.feature.account.setup.domain.DomainContract.UseCase import com.fsck.k9.mail.ServerSettings +import java.util.UUID class CreateAccount( private val accountCreator: AccountCreator, + private val uuidGenerator: () -> String = { UUID.randomUUID().toString() }, ) : UseCase.CreateAccount { override suspend fun execute( emailAddress: String, @@ -18,6 +20,7 @@ class CreateAccount( options: AccountOptions, ): String { val account = Account( + uuid = uuidGenerator(), emailAddress = emailAddress, incomingServerSettings = incomingServerSettings, outgoingServerSettings = outgoingServerSettings, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccountTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccountTest.kt index 81249044e9..eac495081d 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccountTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/domain/usecase/CreateAccountTest.kt @@ -21,6 +21,7 @@ class CreateAccountTest { recordedAccount = account AccountCreatorResult.Success(accountUuid = "uuid") }, + uuidGenerator = { "uuid" }, ) val emailAddress = "user@example.com" @@ -65,6 +66,7 @@ class CreateAccountTest { assertThat(result).isEqualTo("uuid") assertThat(recordedAccount).isEqualTo( Account( + uuid = "uuid", emailAddress = emailAddress, incomingServerSettings = incomingServerSettings, outgoingServerSettings = outgoingServerSettings, -- GitLab From 5694e0934bc4454aaf7799a529eb08e4a596c5d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 15:18:33 +0200 Subject: [PATCH 43/94] Add `account:edit` module --- feature/account/edit/build.gradle.kts | 28 +++++++++++++++++++ .../feature/account/edit/AccountEditModule.kt | 9 ++++++ settings.gradle.kts | 1 + 3 files changed, 38 insertions(+) create mode 100644 feature/account/edit/build.gradle.kts create mode 100644 feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt diff --git a/feature/account/edit/build.gradle.kts b/feature/account/edit/build.gradle.kts new file mode 100644 index 0000000000..3542be5267 --- /dev/null +++ b/feature/account/edit/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + id(ThunderbirdPlugins.Library.androidCompose) +} + +android { + namespace = "app.k9mail.feature.account.edit" + resourcePrefix = "account_edit_" + + buildTypes { + debug { + manifestPlaceholders["appAuthRedirectScheme"] = "FIXME: override this in your app project" + } + release { + manifestPlaceholders["appAuthRedirectScheme"] = "FIXME: override this in your app project" + } + } +} + +dependencies { + implementation(projects.core.ui.compose.designsystem) + implementation(projects.core.common) + + implementation(projects.feature.account.common) + implementation(projects.feature.account.oauth) + implementation(projects.feature.account.server.validation) + + testImplementation(projects.core.ui.compose.testing) +} diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt new file mode 100644 index 0000000000..03413ba6c4 --- /dev/null +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt @@ -0,0 +1,9 @@ +package app.k9mail.feature.account.edit + +import app.k9mail.core.common.coreCommonModule +import app.k9mail.feature.account.oauth.featureAccountOAuthModule +import org.koin.dsl.module + +val accountEditModule = module { + includes(coreCommonModule, featureAccountOAuthModule) +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 4e7da6fab2..391b8e99f6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -45,6 +45,7 @@ include( include( ":feature:account:common", + ":feature:account:edit", ":feature:account:oauth", ":feature:account:setup", ":feature:account:server:certificate", -- GitLab From 61d955f774843e827e7ecccab04402ac6add3a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 17:53:41 +0200 Subject: [PATCH 44/94] Add AccountUpdater contract and implementation --- app-feature-preview/build.gradle.kts | 1 + .../k9mail/feature/preview/FeatureModule.kt | 17 +++++-- .../feature/preview/account/AccountCreator.kt | 13 ------ .../preview/account/InMemoryAccountStore.kt | 28 ++++++++++++ app/k9mail/build.gradle.kts | 1 + .../java/com/fsck/k9/account/AccountModule.kt | 7 +++ .../com/fsck/k9/account/AccountUpdater.kt | 44 +++++++++++++++++++ .../edit/AccountEditExternalContract.kt | 15 +++++++ 8 files changed, 110 insertions(+), 16 deletions(-) delete mode 100644 app-feature-preview/src/main/java/app/k9mail/feature/preview/account/AccountCreator.kt create mode 100644 app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt create mode 100644 app/k9mail/src/main/java/com/fsck/k9/account/AccountUpdater.kt create mode 100644 feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditExternalContract.kt diff --git a/app-feature-preview/build.gradle.kts b/app-feature-preview/build.gradle.kts index a37b72158a..53b5803c20 100644 --- a/app-feature-preview/build.gradle.kts +++ b/app-feature-preview/build.gradle.kts @@ -70,6 +70,7 @@ dependencies { implementation(projects.feature.onboarding) implementation(projects.feature.account.setup) + implementation(projects.feature.account.edit) implementation(libs.appauth) implementation(libs.okhttp) diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt index 5edb78b6cd..43ddc813f0 100644 --- a/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt @@ -1,10 +1,11 @@ package app.k9mail.feature.preview import app.k9mail.core.common.oauth.OAuthConfigurationFactory +import app.k9mail.feature.account.edit.AccountEditExternalContract import app.k9mail.feature.account.setup.AccountSetupExternalContract import app.k9mail.feature.account.setup.featureAccountSetupModule -import app.k9mail.feature.preview.account.AccountCreator import app.k9mail.feature.preview.account.AccountOwnerNameProvider +import app.k9mail.feature.preview.account.InMemoryAccountStore import app.k9mail.feature.preview.auth.AndroidKeyStoreDirectoryProvider import app.k9mail.feature.preview.auth.AppOAuthConfigurationFactory import app.k9mail.feature.preview.auth.DefaultTrustedSocketFactory @@ -15,11 +16,18 @@ import com.fsck.k9.mail.ssl.LocalKeyStore import com.fsck.k9.mail.ssl.TrustManagerFactory import com.fsck.k9.mail.ssl.TrustedSocketFactory import org.koin.core.module.Module +import org.koin.dsl.binds import org.koin.dsl.module val accountModule: Module = module { + single { InMemoryAccountStore() } + .binds( + arrayOf( + AccountSetupExternalContract.AccountCreator::class, + AccountEditExternalContract.AccountUpdater::class, + ), + ) factory { AccountOwnerNameProvider() } - factory { AccountCreator() } } val featureModule: Module = module { @@ -31,5 +39,8 @@ val featureModule: Module = module { single { DefaultTrustedSocketFactory(get(), get()) } single { RealOAuth2TokenProviderFactory(context = get()) } - includes(featureAccountSetupModule, accountModule) + includes( + accountModule, + featureAccountSetupModule, + ) } diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/AccountCreator.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/AccountCreator.kt deleted file mode 100644 index 5048b578c3..0000000000 --- a/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/AccountCreator.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.k9mail.feature.preview.account - -import app.k9mail.feature.account.common.domain.entity.Account -import app.k9mail.feature.account.setup.AccountSetupExternalContract -import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult -import java.util.UUID - -class AccountCreator : AccountSetupExternalContract.AccountCreator { - - override suspend fun createAccount(account: Account): AccountCreatorResult { - return AccountCreatorResult.Success(UUID.randomUUID().toString()) - } -} diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt new file mode 100644 index 0000000000..40787f79f9 --- /dev/null +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt @@ -0,0 +1,28 @@ +package app.k9mail.feature.preview.account + +import app.k9mail.feature.account.common.domain.entity.Account +import app.k9mail.feature.account.edit.AccountEditExternalContract.AccountUpdater +import app.k9mail.feature.account.edit.AccountEditExternalContract.AccountUpdater.AccountUpdaterResult +import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator +import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator.AccountCreatorResult + +class InMemoryAccountStore( + private val accountMap: MutableMap = mutableMapOf(), +) : AccountCreator, AccountUpdater { + + override suspend fun createAccount(account: Account): AccountCreatorResult { + accountMap[account.uuid] = account + + return AccountCreatorResult.Success(account.uuid) + } + + override suspend fun updateAccount(account: Account): AccountUpdaterResult { + return if (!accountMap.containsKey(account.uuid)) { + AccountUpdaterResult.Error("Account not found") + } else { + accountMap[account.uuid] = account + + AccountUpdaterResult.Success(account.uuid) + } + } +} diff --git a/app/k9mail/build.gradle.kts b/app/k9mail/build.gradle.kts index fd0f33f511..bcf60947b3 100644 --- a/app/k9mail/build.gradle.kts +++ b/app/k9mail/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { implementation(projects.feature.launcher) implementation(projects.feature.account.setup) + implementation(projects.feature.account.edit) implementation(libs.androidx.appcompat) implementation(libs.androidx.core.ktx) diff --git a/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt b/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt index e1a250f68d..a695964a63 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt @@ -1,5 +1,6 @@ package com.fsck.k9.account +import app.k9mail.feature.account.edit.AccountEditExternalContract import app.k9mail.feature.account.setup.AccountSetupExternalContract import org.koin.android.ext.koin.androidApplication import org.koin.dsl.module @@ -19,4 +20,10 @@ val newAccountModule = module { context = androidApplication(), ) } + + factory { + AccountUpdater( + preferences = get(), + ) + } } diff --git a/app/k9mail/src/main/java/com/fsck/k9/account/AccountUpdater.kt b/app/k9mail/src/main/java/com/fsck/k9/account/AccountUpdater.kt new file mode 100644 index 0000000000..3a5bd41431 --- /dev/null +++ b/app/k9mail/src/main/java/com/fsck/k9/account/AccountUpdater.kt @@ -0,0 +1,44 @@ +package com.fsck.k9.account + +import app.k9mail.feature.account.common.domain.entity.Account +import app.k9mail.feature.account.edit.AccountEditExternalContract +import app.k9mail.feature.account.edit.AccountEditExternalContract.AccountUpdater.AccountUpdaterResult +import com.fsck.k9.Preferences +import com.fsck.k9.logging.Timber +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class AccountUpdater( + private val preferences: Preferences, + private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO, +) : AccountEditExternalContract.AccountUpdater { + + @Suppress("TooGenericExceptionCaught") + override suspend fun updateAccount(account: Account): AccountUpdaterResult { + return try { + withContext(coroutineDispatcher) { + AccountUpdaterResult.Success(update(account)) + } + } catch (e: Exception) { + Timber.e(e, "Error while updating account") + + AccountUpdaterResult.Error(e.message ?: "Unknown update account error") + } + } + + private fun update(account: Account): String { + val uuid = account.uuid + require(uuid.isNotEmpty()) { "Can't update account without uuid" } + + val existingAccount = preferences.getAccount(uuid) + require(existingAccount != null) { "Can't update non-existing account" } + + existingAccount.incomingServerSettings = account.incomingServerSettings + existingAccount.outgoingServerSettings = account.outgoingServerSettings + + preferences.saveAccount(existingAccount) + + return uuid + } +} diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditExternalContract.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditExternalContract.kt new file mode 100644 index 0000000000..d7c65cd0e1 --- /dev/null +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditExternalContract.kt @@ -0,0 +1,15 @@ +package app.k9mail.feature.account.edit + +import app.k9mail.feature.account.common.domain.entity.Account + +interface AccountEditExternalContract { + + fun interface AccountUpdater { + suspend fun updateAccount(account: Account): AccountUpdaterResult + + sealed interface AccountUpdaterResult { + data class Success(val accountId: String) : AccountUpdaterResult + data class Error(val message: String) : AccountUpdaterResult + } + } +} -- GitLab From 8549bfc554d044702a5f569ed390b91993d968b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 12 Sep 2023 16:35:46 +0200 Subject: [PATCH 45/94] Add newAccount method to preferences to allow creation with given UUID --- app/core/src/main/java/com/fsck/k9/Preferences.kt | 5 ++++- .../src/main/java/com/fsck/k9/account/AccountCreator.kt | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/core/src/main/java/com/fsck/k9/Preferences.kt b/app/core/src/main/java/com/fsck/k9/Preferences.kt index 5b20a58fc6..a8ab74c4fe 100644 --- a/app/core/src/main/java/com/fsck/k9/Preferences.kt +++ b/app/core/src/main/java/com/fsck/k9/Preferences.kt @@ -122,7 +122,6 @@ class Preferences internal constructor( } } - @OptIn(ExperimentalCoroutinesApi::class) override fun getAccountFlow(accountUuid: String): Flow { return callbackFlow { val initialAccount = getAccount(accountUuid) @@ -169,6 +168,10 @@ class Preferences internal constructor( fun newAccount(): Account { val accountUuid = UUID.randomUUID().toString() + return newAccount(accountUuid) + } + + fun newAccount(accountUuid: String): Account { val account = Account(accountUuid) accountPreferenceSerializer.loadDefaults(account) diff --git a/app/k9mail/src/main/java/com/fsck/k9/account/AccountCreator.kt b/app/k9mail/src/main/java/com/fsck/k9/account/AccountCreator.kt index 80496250ae..d5b5dbcab5 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/account/AccountCreator.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/account/AccountCreator.kt @@ -40,7 +40,7 @@ class AccountCreator( } private fun create(account: Account): String { - val newAccount = preferences.newAccount() + val newAccount = preferences.newAccount(account.uuid) newAccount.email = account.emailAddress -- GitLab From 69c373e17837f3c7c5b520d25311f188f8fc782b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Fri, 15 Sep 2023 13:42:50 +0200 Subject: [PATCH 46/94] Rename AccountStateRepository save to set function names --- .../data/InMemoryAccountStateRepository.kt | 12 +++++----- .../common/domain/AccountDomainContract.kt | 12 +++++----- .../preview/PreviewAccountStateRepository.kt | 13 +++++----- .../InMemoryAccountStateRepositoryTest.kt | 24 +++++++++---------- .../IncomingServerSettingsViewModel.kt | 2 +- .../OutgoingServerSettingsViewModel.kt | 2 +- .../IncomingServerSettingsViewModelTest.kt | 2 +- .../OutgoingServerSettingsViewModelTest.kt | 2 +- .../ui/BaseServerValidationViewModel.kt | 2 +- .../account/setup/ui/AccountSetupViewModel.kt | 2 +- .../AccountAutoDiscoveryViewModel.kt | 2 +- .../ui/options/AccountOptionsViewModel.kt | 2 +- .../setup/ui/AccountSetupViewModelTest.kt | 2 +- 13 files changed, 40 insertions(+), 39 deletions(-) diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepository.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepository.kt index 3a8c245bb6..7cd368faff 100644 --- a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepository.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepository.kt @@ -15,27 +15,27 @@ class InMemoryAccountStateRepository( return state } - override fun save(accountState: AccountState) { + override fun setState(accountState: AccountState) { state = accountState } - override fun saveEmailAddress(emailAddress: String) { + override fun setEmailAddress(emailAddress: String) { state = state.copy(emailAddress = emailAddress) } - override fun saveIncomingServerSettings(serverSettings: ServerSettings) { + override fun setIncomingServerSettings(serverSettings: ServerSettings) { state = state.copy(incomingServerSettings = serverSettings) } - override fun saveOutgoingServerSettings(serverSettings: ServerSettings) { + override fun setOutgoingServerSettings(serverSettings: ServerSettings) { state = state.copy(outgoingServerSettings = serverSettings) } - override fun saveAuthorizationState(authorizationState: AuthorizationState) { + override fun setAuthorizationState(authorizationState: AuthorizationState) { state = state.copy(authorizationState = authorizationState) } - override fun saveOptions(options: AccountOptions) { + override fun setOptions(options: AccountOptions) { state = state.copy(options = options) } diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/AccountDomainContract.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/AccountDomainContract.kt index 1fd0fe7f42..4d325904b2 100644 --- a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/AccountDomainContract.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/domain/AccountDomainContract.kt @@ -10,17 +10,17 @@ interface AccountDomainContract { interface AccountStateRepository { fun getState(): AccountState - fun save(accountState: AccountState) + fun setState(accountState: AccountState) - fun saveEmailAddress(emailAddress: String) + fun setEmailAddress(emailAddress: String) - fun saveIncomingServerSettings(serverSettings: ServerSettings) + fun setIncomingServerSettings(serverSettings: ServerSettings) - fun saveOutgoingServerSettings(serverSettings: ServerSettings) + fun setOutgoingServerSettings(serverSettings: ServerSettings) - fun saveAuthorizationState(authorizationState: AuthorizationState) + fun setAuthorizationState(authorizationState: AuthorizationState) - fun saveOptions(options: AccountOptions) + fun setOptions(options: AccountOptions) fun clear() } diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/preview/PreviewAccountStateRepository.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/preview/PreviewAccountStateRepository.kt index 627f48e2e2..e04aada6a4 100644 --- a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/preview/PreviewAccountStateRepository.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/ui/preview/PreviewAccountStateRepository.kt @@ -9,6 +9,7 @@ import com.fsck.k9.mail.AuthType import com.fsck.k9.mail.ServerSettings class PreviewAccountStateRepository : AccountDomainContract.AccountStateRepository { + override fun getState(): AccountState = AccountState( emailAddress = "test@example.com", incomingServerSettings = ServerSettings( @@ -33,17 +34,17 @@ class PreviewAccountStateRepository : AccountDomainContract.AccountStateReposito ), ) - override fun save(accountState: AccountState) = Unit + override fun setState(accountState: AccountState) = Unit - override fun saveEmailAddress(emailAddress: String) = Unit + override fun setEmailAddress(emailAddress: String) = Unit - override fun saveIncomingServerSettings(serverSettings: ServerSettings) = Unit + override fun setIncomingServerSettings(serverSettings: ServerSettings) = Unit - override fun saveOutgoingServerSettings(serverSettings: ServerSettings) = Unit + override fun setOutgoingServerSettings(serverSettings: ServerSettings) = Unit - override fun saveAuthorizationState(authorizationState: AuthorizationState) = Unit + override fun setAuthorizationState(authorizationState: AuthorizationState) = Unit - override fun saveOptions(options: AccountOptions) = Unit + override fun setOptions(options: AccountOptions) = Unit override fun clear() = Unit } diff --git a/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt index 0e22332bfb..5d52ec4935 100644 --- a/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt +++ b/feature/account/common/src/test/kotlin/app/k9mail/feature/account/common/data/InMemoryAccountStateRepositoryTest.kt @@ -31,7 +31,7 @@ class InMemoryAccountStateRepositoryTest { } @Test - fun `should save state`() { + fun `should set state`() { val testSubject = InMemoryAccountStateRepository( AccountState( uuid = "uuid", @@ -58,56 +58,56 @@ class InMemoryAccountStateRepositoryTest { ), ) - testSubject.save(newState) + testSubject.setState(newState) assertThat(testSubject.getState()).isEqualTo(newState) } @Test - fun `should save email address`() { + fun `should set email address`() { val testSubject = InMemoryAccountStateRepository() - testSubject.saveEmailAddress("emailAddress") + testSubject.setEmailAddress("emailAddress") assertThat(testSubject.getState().emailAddress) .isEqualTo("emailAddress") } @Test - fun `should save incoming server settings`() { + fun `should set incoming server settings`() { val testSubject = InMemoryAccountStateRepository() - testSubject.saveIncomingServerSettings(INCOMING_SERVER_SETTINGS) + testSubject.setIncomingServerSettings(INCOMING_SERVER_SETTINGS) assertThat(testSubject.getState().incomingServerSettings) .isEqualTo(INCOMING_SERVER_SETTINGS) } @Test - fun `should save outgoing server settings`() { + fun `should set outgoing server settings`() { val testSubject = InMemoryAccountStateRepository() - testSubject.saveOutgoingServerSettings(OUTGOING_SERVER_SETTINGS) + testSubject.setOutgoingServerSettings(OUTGOING_SERVER_SETTINGS) assertThat(testSubject.getState().outgoingServerSettings) .isEqualTo(OUTGOING_SERVER_SETTINGS) } @Test - fun `should save authorization state`() { + fun `should set authorization state`() { val testSubject = InMemoryAccountStateRepository() - testSubject.saveAuthorizationState(AuthorizationState("authorizationState")) + testSubject.setAuthorizationState(AuthorizationState("authorizationState")) assertThat(testSubject.getState().authorizationState) .isEqualTo(AuthorizationState("authorizationState")) } @Test - fun `should save options`() { + fun `should set options`() { val testSubject = InMemoryAccountStateRepository() - testSubject.saveOptions(OPTIONS) + testSubject.setOptions(OPTIONS) assertThat(testSubject.getState().options) .isEqualTo(OPTIONS) diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt index 2fcd516201..4770a61f8a 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt @@ -115,7 +115,7 @@ class IncomingServerSettingsViewModel( } if (!hasError) { - accountStateRepository.saveIncomingServerSettings(state.value.toServerSettings()) + accountStateRepository.setIncomingServerSettings(state.value.toServerSettings()) navigateNext() } } diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt index 75a02f78bb..3c7c5b0881 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt @@ -78,7 +78,7 @@ class OutgoingServerSettingsViewModel( } if (!hasError) { - accountStateRepository.saveOutgoingServerSettings(state.value.toServerSettings()) + accountStateRepository.setOutgoingServerSettings(state.value.toServerSettings()) navigateNext() } } diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt index fc4bf185e7..dd225e0d81 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt @@ -56,7 +56,7 @@ class IncomingServerSettingsViewModelTest { ) val turbines = turbinesWithInitialStateCheck(testSubject, State()) - repository.save(accountState) + repository.setState(accountState) testSubject.event(Event.LoadAccountState) diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt index 2907c3cf05..a055a0651c 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt @@ -54,7 +54,7 @@ class OutgoingServerSettingsViewModelTest { ) val turbines = turbinesWithInitialStateCheck(testSubject, State()) - repository.save(accountState) + repository.setState(accountState) testSubject.event(Event.LoadAccountState) diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/BaseServerValidationViewModel.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/BaseServerValidationViewModel.kt index acb629f66f..57fe861160 100644 --- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/BaseServerValidationViewModel.kt +++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ui/BaseServerValidationViewModel.kt @@ -102,7 +102,7 @@ abstract class BaseServerValidationViewModel( private fun onOAuthResult(result: OAuthResult) { if (result is OAuthResult.Success) { - accountStateRepository.saveAuthorizationState(result.authorizationState) + accountStateRepository.setAuthorizationState(result.authorizationState) updateState { it.copy( needsAuthorization = false, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModel.kt index 2e3a90f120..5c38c8a25c 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModel.kt @@ -104,7 +104,7 @@ class AccountSetupViewModel( private fun changeToSetupStep(setupStep: SetupStep) { if (setupStep == SetupStep.AUTO_CONFIG) { - accountStateRepository.saveAuthorizationState(AuthorizationState(null)) + accountStateRepository.setAuthorizationState(AuthorizationState(null)) } updateState { diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt index 8aad922fb3..29b774fda3 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryViewModel.kt @@ -250,7 +250,7 @@ internal class AccountAutoDiscoveryViewModel( private fun navigateBack() = emitEffect(Effect.NavigateBack) private fun navigateNext(isAutomaticConfig: Boolean) { - accountStateRepository.save(state.value.toAccountState()) + accountStateRepository.setState(state.value.toAccountState()) emitEffect(Effect.NavigateNext(isAutomaticConfig)) } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModel.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModel.kt index 9f2b4196cb..e255e17db3 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModel.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/options/AccountOptionsViewModel.kt @@ -89,7 +89,7 @@ internal class AccountOptionsViewModel( } if (!hasError) { - accountStateRepository.saveOptions(state.value.toAccountOptions()) + accountStateRepository.setOptions(state.value.toAccountOptions()) navigateNext() } } diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModelTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModelTest.kt index 3d07a7f9e9..db4d38547c 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModelTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupViewModelTest.kt @@ -132,7 +132,7 @@ class AccountSetupViewModelTest { prop(State::setupStep).isEqualTo(SetupStep.OPTIONS) } - accountStateRepository.save(expectedAccountState) + accountStateRepository.setState(expectedAccountState) viewModel.event(AccountSetupContract.Event.OnNext) -- GitLab From 5c24e080590b5bdaec0eecb8c461ed88d39b97dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Mon, 18 Sep 2023 16:25:22 +0200 Subject: [PATCH 47/94] Split workflow run into multiple steps --- .github/workflows/android.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index d3e2769cd2..d5ad12ac69 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -28,4 +28,11 @@ jobs: distribution: temurin java-version: 17 - uses: gradle/gradle-build-action@v2 - - run: ./gradlew assembleDebug detekt spotlessCheck testsOnCi + - name: Build + run: ./gradlew assembleDebug + - name: Detekt + run: ./gradlew detekt + - name: Spotless + run: ./gradlew spotlessCheck + - name: Tests + run: ./gradlew testsOnCi -- GitLab From 713ff9ea3bb62cd97f8508dd7097e241d9abf875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Mon, 18 Sep 2023 15:49:14 +0200 Subject: [PATCH 48/94] Fix memory issues, taken from NowInAndroid example App --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d90d2679b5..555e9e3b42 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,7 @@ android.defaults.buildfeatures.shaders=false # Gradle ## Ensure important default jvmargs aren't overwritten. See https://github.com/gradle/gradle/issues/19750 -org.gradle.jvmargs=-Xmx4G -Xms1G -XX:MaxMetaspaceSize=1536M -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError +org.gradle.jvmargs=-Xmx6g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError org.gradle.parallel=true -- GitLab From d142bbef9619fb3b0ef91e148d977805683b141c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Mon, 18 Sep 2023 17:13:58 +0200 Subject: [PATCH 49/94] Add ci gradle.properties and move quality checks to the start --- .github/ci-gradle.properties | 6 ++++++ .github/workflows/android.yml | 21 ++++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 .github/ci-gradle.properties diff --git a/.github/ci-gradle.properties b/.github/ci-gradle.properties new file mode 100644 index 0000000000..7de8afc3ae --- /dev/null +++ b/.github/ci-gradle.properties @@ -0,0 +1,6 @@ +org.gradle.daemon=false +org.gradle.parallel=true +org.gradle.workers.max=2 + +kotlin.incremental=false +kotlin.compiler.execution.strategy=in-process diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index d5ad12ac69..8ace88da18 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -21,18 +21,29 @@ jobs: build: runs-on: ubuntu-latest + timeout-minutes: 90 + steps: - uses: actions/checkout@v4 + + - name: Copy CI gradle.properties + run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties + - uses: actions/setup-java@v3 with: distribution: temurin java-version: 17 + - uses: gradle/gradle-build-action@v2 + + - name: Quality - Spotless + run: ./gradlew spotlessCheck + + - name: Quality - Detekt + run: ./gradlew detekt + - name: Build run: ./gradlew assembleDebug - - name: Detekt - run: ./gradlew detekt - - name: Spotless - run: ./gradlew spotlessCheck - - name: Tests + + - name: Test run: ./gradlew testsOnCi -- GitLab From d83259a5ee2852b7037c3e5c4d60d507d3e52098 Mon Sep 17 00:00:00 2001 From: cketti Date: Mon, 18 Sep 2023 17:40:13 +0200 Subject: [PATCH 50/94] HTML-encode header field values when displaying message/rfc822 parts --- .../mailstore/MessageViewInfoExtractor.java | 8 ++++--- .../MessageViewInfoExtractorTest.java | 24 +++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/app/core/src/main/java/com/fsck/k9/mailstore/MessageViewInfoExtractor.java b/app/core/src/main/java/com/fsck/k9/mailstore/MessageViewInfoExtractor.java index b98c801464..8b142e594b 100644 --- a/app/core/src/main/java/com/fsck/k9/mailstore/MessageViewInfoExtractor.java +++ b/app/core/src/main/java/com/fsck/k9/mailstore/MessageViewInfoExtractor.java @@ -6,6 +6,8 @@ import java.util.Collections; import java.util.Date; import java.util.List; +import android.text.TextUtils; + import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.annotation.WorkerThread; @@ -347,7 +349,7 @@ public class MessageViewInfoExtractor { String filename = getPartName(part); html.append("

"); - html.append(filename); + html.append(TextUtils.htmlEncode(filename)); html.append("

"); } } @@ -540,10 +542,10 @@ public class MessageViewInfoExtractor { */ private static void addTableRow(StringBuilder html, String header, String value) { html.append(""); - html.append(header); + html.append(TextUtils.htmlEncode(header)); html.append(""); html.append(""); - html.append(value); + html.append(TextUtils.htmlEncode(value)); html.append(""); } diff --git a/app/core/src/test/java/com/fsck/k9/mailstore/MessageViewInfoExtractorTest.java b/app/core/src/test/java/com/fsck/k9/mailstore/MessageViewInfoExtractorTest.java index 6de424caa2..8d5a057a8a 100644 --- a/app/core/src/test/java/com/fsck/k9/mailstore/MessageViewInfoExtractorTest.java +++ b/app/core/src/test/java/com/fsck/k9/mailstore/MessageViewInfoExtractorTest.java @@ -251,16 +251,16 @@ public class MessageViewInfoExtractorTest extends K9RobolectricTest { // Create message/rfc822 body MimeMessage innerMessage = new MimeMessage(); innerMessage.addSentDate(new Date(112, 2, 17), false); - innerMessage.setHeader("To", "to@example.com"); - innerMessage.setSubject("Subject"); - innerMessage.setFrom(new Address("from@example.com")); + innerMessage.setHeader("To", "Recipient "); + innerMessage.setSubject("Subject with characters that need HTML encoding: \"&<>"); + innerMessage.setFrom(new Address("from@example.com", "Display name & email address")); MimeMessageHelper.setBody(innerMessage, innerBody); // Create multipart/mixed part MimeMultipart multipart = MimeMultipart.newInstance(); MimeBodyPart bodyPart1 = new MimeBodyPart(textBody, "text/plain"); MimeBodyPart bodyPart2 = new MimeBodyPart(innerMessage, "message/rfc822"); - bodyPart2.setHeader("Content-Disposition", "inline; filename=\"message.eml\""); + bodyPart2.setHeader("Content-Disposition", "inline; filename=\"message&special_char.eml\""); multipart.addBodyPart(bodyPart1); multipart.addBodyPart(bodyPart2); @@ -277,12 +277,12 @@ public class MessageViewInfoExtractorTest extends K9RobolectricTest { String expectedText = BODY_TEXT + "\r\n\r\n" + - "----- message.eml ------------------------------------------------------" + + "----- message&special_char.eml -----------------------------------------" + "\r\n\r\n" + - "From: from@example.com" + "\r\n" + - "To: to@example.com" + "\r\n" + + "From: Display name & email address " + "\r\n" + + "To: Recipient " + "\r\n" + "Sent: Sat Mar 17 00:00:00 GMT+01:00 2012" + "\r\n" + - "Subject: Subject" + "\r\n" + + "Subject: Subject with characters that need HTML encoding: \"&<>" + "\r\n" + "\r\n" + innerBodyText; String expectedHtml = @@ -290,20 +290,20 @@ public class MessageViewInfoExtractorTest extends K9RobolectricTest { BODY_TEXT_HTML + "" + "

message.eml

" + + "1px solid #000\">message&special_char.eml

" + "" + "" + "" + - "" + + "" + "" + "" + - "" + + "" + "" + "" + "" + "" + "" + - "" + + "" + "" + "
From:from@example.comDisplay name & email address <from@example.com>
To:to@example.comRecipient <to@example.com>
Sent:Sat Mar 17 00:00:00 GMT+01:00 2012
Subject:SubjectSubject with characters that need HTML encoding: "&<>
" + "
" +
-- 
GitLab


From 5bf877f562f549fb3cee0a927f610d7264dbfc5f Mon Sep 17 00:00:00 2001
From: cketti 
Date: Mon, 18 Sep 2023 19:35:53 +0200
Subject: [PATCH 51/94] Allow `
+              
+            
+            """.compactHtml()
+
+        val result = htmlSanitizer.sanitize(html)
+
+        assertThat(result.toCompactString()).isEqualTo(html)
+    }
+
     private fun assertTagsNotStripped(element: String) {
         val html = """<$element>some text"""
 
-- 
GitLab


From 0abee28d05d19bdf2603af670c808e1adf90d0ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Mon, 18 Sep 2023 14:44:05 +0200
Subject: [PATCH 52/94] Bump Android Gradle Plugin 8.0.2 -> 8.1.1

---
 build-plugin/src/main/kotlin/AndroidExtension.kt | 4 ++--
 gradle/libs.versions.toml                        | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/build-plugin/src/main/kotlin/AndroidExtension.kt b/build-plugin/src/main/kotlin/AndroidExtension.kt
index 5db5fdcb33..9a1878473b 100644
--- a/build-plugin/src/main/kotlin/AndroidExtension.kt
+++ b/build-plugin/src/main/kotlin/AndroidExtension.kt
@@ -2,7 +2,7 @@ import com.android.build.api.dsl.CommonExtension
 import org.gradle.accessors.dm.LibrariesForLibs
 import org.gradle.api.artifacts.dsl.DependencyHandler
 
-internal fun CommonExtension<*, *, *, *>.configureSharedConfig() {
+internal fun CommonExtension<*, *, *, *, *>.configureSharedConfig() {
     compileSdk = ThunderbirdProjectConfig.androidSdkCompile
 
     defaultConfig {
@@ -29,7 +29,7 @@ internal fun CommonExtension<*, *, *, *>.configureSharedConfig() {
     }
 }
 
-internal fun CommonExtension<*, *, *, *>.configureSharedComposeConfig(
+internal fun CommonExtension<*, *, *, *, *>.configureSharedComposeConfig(
     libs: LibrariesForLibs,
 ) {
     buildFeatures {
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index aed59613cf..a9e167bbb7 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -3,7 +3,7 @@
 
 [versions]
 gradle = "8.3"
-androidGradlePlugin = "8.0.2"
+androidGradlePlugin = "8.1.1"
 ktlint = "0.50.0"
 
 kotlin = "1.8.22"
-- 
GitLab


From 5c5fb5cedf2dc84cd4a85d0e38b16fe5feb7b635 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Mon, 18 Sep 2023 14:50:15 +0200
Subject: [PATCH 53/94] Bump dependency check 0.46.0 -> 0.48.0

---
 gradle/libs.versions.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a9e167bbb7..2ccc66fb2f 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -50,7 +50,7 @@ kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref =
 kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
 spotless = "com.diffplug.spotless:6.21.0"
 detekt = "io.gitlab.arturbosch.detekt:1.23.0"
-dependency-check = "com.github.ben-manes.versions:0.46.0"
+dependency-check = "com.github.ben-manes.versions:0.48.0"
 
 [libraries]
 desugar = "com.android.tools:desugar_jdk_libs:2.0.3"
-- 
GitLab


From a0e6fd9f5c6e415afd4e1294bc0ee8a6df80d2c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Mon, 18 Sep 2023 15:17:36 +0200
Subject: [PATCH 54/94] Bump Android SDK compile version 33 -> 34 and
 dependencies for Compose 1.5.1

- Kotlin 1.8.22 -> 1.9.11
- Compose BOM 2023.06.01 -> 2023.09.00
- Compose compiler 1.4.8 -> 1.5.3
- AndroidX Lifecycle 2.6.1 -> 2.6.2
- AndroidX Navigation 2.6.0 -> 2.7.2
- AndroidX Core 1.10.1 -> 1.12.0
- AndroidX Annotation 1.6.0 -> 1.7.0
- Accompanist 0.30.1 -> 0.32.0
- Koin 3.4.3 -> 3.5.0
- Okio 3.4.0 -> 3.5.0
- Mockito 5.4.0 -> 5.5.0
- Robolectric 4.9.2 -> 4.10.3
---
 .../ui/catalog/ui/common/PagedContent.kt      | 11 ++++--
 .../main/kotlin/ThunderbirdProjectConfig.kt   |  2 +-
 gradle/libs.versions.toml                     | 34 +++++++++----------
 3 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/PagedContent.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/PagedContent.kt
index 0a45150457..c86528037d 100644
--- a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/PagedContent.kt
+++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/PagedContent.kt
@@ -32,7 +32,12 @@ fun  PagedContent(
     modifier: Modifier = Modifier,
     onRenderPage: LazyGridScope.(T) -> Unit,
 ) {
-    val pagerState = rememberPagerState(initialPage = pages.indexOf(initialPage))
+    val pagerState = rememberPagerState(
+        initialPage = pages.indexOf(initialPage),
+        initialPageOffsetFraction = 0f,
+    ) {
+        pages.size
+    }
     val coroutineScope = rememberCoroutineScope()
 
     Column(
@@ -55,14 +60,14 @@ fun  PagedContent(
         }
         ResponsiveContentWithBackground {
             HorizontalPager(
-                pageCount = pages.size,
                 state = pagerState,
                 modifier = Modifier
                     .fillMaxSize(),
             ) { page ->
                 LazyVerticalGrid(
                     columns = GridCells.Adaptive(300.dp),
-                    modifier = Modifier.fillMaxSize()
+                    modifier = Modifier
+                        .fillMaxSize()
                         .imePadding(),
                     horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
                     verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
diff --git a/build-plugin/src/main/kotlin/ThunderbirdProjectConfig.kt b/build-plugin/src/main/kotlin/ThunderbirdProjectConfig.kt
index c16a74dd5c..493ae4e1a0 100644
--- a/build-plugin/src/main/kotlin/ThunderbirdProjectConfig.kt
+++ b/build-plugin/src/main/kotlin/ThunderbirdProjectConfig.kt
@@ -6,5 +6,5 @@ object ThunderbirdProjectConfig {
 
     const val androidSdkMin = 21
     const val androidSdkTarget = 31
-    const val androidSdkCompile = 33
+    const val androidSdkCompile = 34
 }
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 2ccc66fb2f..8c3114ddde 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -6,45 +6,45 @@ gradle = "8.3"
 androidGradlePlugin = "8.1.1"
 ktlint = "0.50.0"
 
-kotlin = "1.8.22"
+kotlin = "1.9.10"
 kotlinxCoroutines = "1.7.3"
 jetbrainsAnnotations = "24.0.1"
 androidxAppCompat = "1.6.1"
 androidxActivity = "1.7.2"
 androidxRecyclerView = "1.3.1"
-androidxLifecycle = "2.6.1"
-androidxNavigation = "2.6.0"
+androidxLifecycle = "2.6.2"
+androidxNavigation = "2.7.2"
 androidxConstraintLayout = "2.1.4"
 androidxFragment = "1.6.1"
-androidxCore = "1.10.1"
+androidxCore = "1.12.0"
 androidxCoreSplashscreen = "1.0.1"
 androidxPreference = "1.2.1"
 androidxDrawerLayout = "1.1.1"
 androidxTransition = "1.4.1"
-androidxComposeCompiler = "1.4.8"
+androidxComposeCompiler = "1.5.3"
 # https://developer.android.com/jetpack/compose/bom/bom-mapping
-androidxComposeBom = "2023.06.01"
-androidxComposeMaterial = "1.4.3"
+androidxComposeBom = "2023.09.00"
+androidxComposeMaterial = "1.5.1"
 androidxComposeMaterial3 = "1.1.1"
-accompanist = "0.30.1"
+accompanist = "0.32.0"
 fastAdapter = "5.7.0"
 preferencesFix = "1.1.0"
 timber = "5.0.1"
-koinCore = "3.4.3"
-koinAndroid = "3.4.3"
-koinAndroidCompose = "3.4.6"
-koinTest = "3.4.3"
+koinCore = "3.5.0"
+koinAndroid = "3.5.0"
+koinAndroidCompose = "3.5.0"
+koinTest = "3.5.0"
 mime4j = "0.8.9"
 okhttp = "4.11.0"
 glide = "4.16.0"
 moshi = "1.15.0"
-mockito = "5.4.0"
+mockito = "5.5.0"
 
 [plugins]
 android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
 android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }
 android-lint = { id = "com.android.lint", version.ref = "androidGradlePlugin" }
-ksp = "com.google.devtools.ksp:1.8.22-1.0.11"
+ksp = "com.google.devtools.ksp:1.9.10-1.0.13"
 kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
 kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
 kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
@@ -71,7 +71,7 @@ androidx-lifecycle-livedata-ktx = { module = "androidx.lifecycle:lifecycle-lived
 androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidxLifecycle" }
 androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel", version.ref = "androidxLifecycle" }
 androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidxLifecycle" }
-androidx-annotation = "androidx.annotation:annotation:1.6.0"
+androidx-annotation = "androidx.annotation:annotation:1.7.0"
 androidx-biometric = "androidx.biometric:biometric:1.1.0"
 androidx-navigation-fragment = { module = "androidx.navigation:navigation-fragment", version.ref = "androidxNavigation" }
 androidx-navigation-ui = { module = "androidx.navigation:navigation-ui", version.ref = "androidxNavigation" }
@@ -111,7 +111,7 @@ materialdrawer = "com.mikepenz:materialdrawer:8.4.5"
 preferencex = { module = "com.takisoft.preferencex:preferencex", version.ref = "preferencesFix" }
 preferencex-datetimepicker = { module = "com.takisoft.preferencex:preferencex-datetimepicker", version.ref = "preferencesFix" }
 preferencex-colorpicker = { module = "com.takisoft.preferencex:preferencex-colorpicker", version.ref = "preferencesFix" }
-okio = "com.squareup.okio:okio:3.4.0"
+okio = "com.squareup.okio:okio:3.5.0"
 moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" }
 moshi-kotlin-codegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi" }
 timber = "com.jakewharton.timber:timber:5.0.1"
@@ -145,7 +145,7 @@ xmlpull = "com.github.cketti:xmlpull-extracted-from-android:1.0"
 kxml2 = "com.github.cketti:kxml2-extracted-from-android:1.0"
 
 junit = "junit:junit:4.13.2"
-robolectric = "org.robolectric:robolectric:4.9.2"
+robolectric = "org.robolectric:robolectric:4.10.3"
 mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" }
 mockito-kotlin = "org.mockito.kotlin:mockito-kotlin:5.1.0"
 turbine = "app.cash.turbine:turbine:0.13.0"
-- 
GitLab


From 5d4f6e429180694ca820e39aa5093f1d8b76a77a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Mon, 18 Sep 2023 15:48:37 +0200
Subject: [PATCH 55/94] Change Lint warningsAsErrors to false to avoid build
 failure when a dependency is outdated

---
 build-plugin/src/main/kotlin/AndroidExtension.kt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build-plugin/src/main/kotlin/AndroidExtension.kt b/build-plugin/src/main/kotlin/AndroidExtension.kt
index 9a1878473b..6fa5d3f649 100644
--- a/build-plugin/src/main/kotlin/AndroidExtension.kt
+++ b/build-plugin/src/main/kotlin/AndroidExtension.kt
@@ -41,7 +41,7 @@ internal fun CommonExtension<*, *, *, *, *>.configureSharedComposeConfig(
     }
 
     lint {
-        warningsAsErrors = true
+        warningsAsErrors = false
         abortOnError = true
     }
 
-- 
GitLab


From 180b6af2f9d94dff116371a76a4f552a45f2ce3c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Tue, 19 Sep 2023 11:24:07 +0200
Subject: [PATCH 56/94] Add ContentLoadingErrorView to design system

---
 .../catalog/ui/common/list/SectionInfoItem.kt | 31 +++++++
 .../catalog/ui/molecule/items/StateItems.kt   | 61 +++++++++++++
 .../molecule/ContentLoadingErrorView.kt       | 88 +++++++++++++++++++
 3 files changed, 180 insertions(+)
 create mode 100644 app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/list/SectionInfoItem.kt
 create mode 100644 core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ContentLoadingErrorView.kt

diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/list/SectionInfoItem.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/list/SectionInfoItem.kt
new file mode 100644
index 0000000000..dd063ef233
--- /dev/null
+++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/list/SectionInfoItem.kt
@@ -0,0 +1,31 @@
+package app.k9mail.ui.catalog.ui.common.list
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.grid.GridItemSpan
+import androidx.compose.foundation.lazy.grid.LazyGridScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import app.k9mail.core.ui.compose.designsystem.atom.text.TextCaption
+import app.k9mail.core.ui.compose.theme.MainTheme
+
+fun LazyGridScope.sectionInfoItem(
+    text: String,
+) {
+    item(span = { GridItemSpan(maxLineSpan) }) {
+        Column(
+            modifier = Modifier
+                .fillMaxWidth()
+                .padding(
+                    start = MainTheme.spacings.double,
+                    end = MainTheme.spacings.double,
+                ),
+            horizontalAlignment = Alignment.CenterHorizontally,
+        ) {
+            TextCaption(
+                text = text,
+            )
+        }
+    }
+}
diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/molecule/items/StateItems.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/molecule/items/StateItems.kt
index 3bd37e2fa1..ad3d56081e 100644
--- a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/molecule/items/StateItems.kt
+++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/molecule/items/StateItems.kt
@@ -1,10 +1,23 @@
 package app.k9mail.ui.catalog.ui.molecule.items
 
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.lazy.grid.LazyGridScope
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import app.k9mail.core.ui.compose.designsystem.atom.text.TextSubtitle1
+import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorState
+import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorView
 import app.k9mail.core.ui.compose.designsystem.molecule.ErrorView
 import app.k9mail.core.ui.compose.designsystem.molecule.LoadingView
 import app.k9mail.ui.catalog.ui.common.list.ItemOutlined
 import app.k9mail.ui.catalog.ui.common.list.sectionHeaderItem
+import app.k9mail.ui.catalog.ui.common.list.sectionInfoItem
 import app.k9mail.ui.catalog.ui.common.list.sectionSubtitleItem
 
 fun LazyGridScope.stateItems() {
@@ -33,4 +46,52 @@ fun LazyGridScope.stateItems() {
             )
         }
     }
+
+    sectionHeaderItem(text = "ContentLoadingErrorView")
+    sectionInfoItem(text = "Click below to change state")
+    item {
+        Column {
+            ItemOutlined {
+                StatefulContentLoadingErrorState()
+            }
+        }
+    }
+}
+
+@Composable
+private fun StatefulContentLoadingErrorState() {
+    val state = remember {
+        mutableStateOf(ContentLoadingErrorState.Loading)
+    }
+
+    ContentLoadingErrorView(
+        state = state.value,
+        modifier = Modifier
+            .clickable {
+                when (state.value) {
+                    ContentLoadingErrorState.Loading -> {
+                        state.value = ContentLoadingErrorState.Content
+                    }
+
+                    ContentLoadingErrorState.Content -> {
+                        state.value = ContentLoadingErrorState.Error
+                    }
+
+                    ContentLoadingErrorState.Error -> {
+                        state.value = ContentLoadingErrorState.Loading
+                    }
+                }
+            }
+            .height(200.dp)
+            .fillMaxSize(),
+        error = {
+            TextSubtitle1(text = "Error")
+        },
+        loading = {
+            TextSubtitle1(text = "Loading...")
+        },
+        content = {
+            TextSubtitle1(text = "Content")
+        },
+    )
 }
diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ContentLoadingErrorView.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ContentLoadingErrorView.kt
new file mode 100644
index 0000000000..f1d7f82a9f
--- /dev/null
+++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ContentLoadingErrorView.kt
@@ -0,0 +1,88 @@
+package app.k9mail.core.ui.compose.designsystem.molecule
+
+import androidx.compose.animation.AnimatedContent
+import androidx.compose.animation.ExperimentalAnimationApi
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import app.k9mail.core.ui.compose.designsystem.atom.text.TextSubtitle1
+import app.k9mail.core.ui.compose.theme.PreviewWithThemes
+
+@OptIn(ExperimentalAnimationApi::class)
+@Composable
+fun ContentLoadingErrorView(
+    state: ContentLoadingErrorState,
+    loading: @Composable () -> Unit,
+    error: @Composable () -> Unit,
+    modifier: Modifier = Modifier,
+    contentAlignment: Alignment = Alignment.Center,
+    content: @Composable () -> Unit,
+) {
+    Box(
+        modifier = modifier,
+        contentAlignment = contentAlignment,
+    ) {
+        AnimatedContent(
+            targetState = state,
+            label = "CleView",
+        ) { targetState ->
+            when (targetState) {
+                ContentLoadingErrorState.Loading -> loading()
+                ContentLoadingErrorState.Content -> content()
+                ContentLoadingErrorState.Error -> error()
+            }
+        }
+    }
+}
+
+sealed interface ContentLoadingErrorState {
+    object Loading : ContentLoadingErrorState
+    object Content : ContentLoadingErrorState
+    object Error : ContentLoadingErrorState
+}
+
+@Composable
+@Preview(showBackground = true)
+internal fun ContentLoadingErrorViewPreview() {
+    PreviewWithThemes {
+        val state = remember {
+            mutableStateOf(ContentLoadingErrorState.Loading)
+        }
+
+        ContentLoadingErrorView(
+            state = state.value,
+            modifier = Modifier
+                .clickable {
+                    when (state.value) {
+                        ContentLoadingErrorState.Loading -> {
+                            state.value = ContentLoadingErrorState.Content
+                        }
+
+                        ContentLoadingErrorState.Content -> {
+                            state.value = ContentLoadingErrorState.Error
+                        }
+
+                        ContentLoadingErrorState.Error -> {
+                            state.value = ContentLoadingErrorState.Loading
+                        }
+                    }
+                }
+                .fillMaxSize(),
+            error = {
+                TextSubtitle1(text = "Error")
+            },
+            loading = {
+                TextSubtitle1(text = "Loading...")
+            },
+            content = {
+                TextSubtitle1(text = "Content")
+            },
+        )
+    }
+}
-- 
GitLab


From 16768c8e8da1580dc39f21a032180415e6e8045d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Tue, 19 Sep 2023 11:40:19 +0200
Subject: [PATCH 57/94] Change AccountAutoDiscoveryContent to
 ContentLoadingErrorView

---
 .../AccountAutoDiscoveryContent.kt            | 56 +++++++++++--------
 1 file changed, 34 insertions(+), 22 deletions(-)

diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt
index 0b515289f3..ef1587a180 100644
--- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt
+++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt
@@ -8,18 +8,21 @@ import androidx.compose.foundation.layout.imePadding
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.res.stringResource
 import app.k9mail.core.ui.compose.common.DevicePreviews
+import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorState
+import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorView
+import app.k9mail.core.ui.compose.designsystem.molecule.ErrorView
+import app.k9mail.core.ui.compose.designsystem.molecule.LoadingView
 import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
 import app.k9mail.core.ui.compose.theme.K9Theme
 import app.k9mail.core.ui.compose.theme.MainTheme
 import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
-import app.k9mail.feature.account.common.ui.item.ErrorItem
-import app.k9mail.feature.account.common.ui.item.LoadingItem
 import app.k9mail.feature.account.oauth.ui.AccountOAuthContract
 import app.k9mail.feature.account.oauth.ui.preview.PreviewAccountOAuthViewModel
 import app.k9mail.feature.account.setup.R
@@ -43,28 +46,37 @@ internal fun AccountAutoDiscoveryContent(
             .then(modifier),
     ) {
         val resources = LocalContext.current.resources
+        val cleState = remember(key1 = state.isLoading, key2 = state.error) {
+            when {
+                state.isLoading -> ContentLoadingErrorState.Loading
+                state.error != null -> ContentLoadingErrorState.Error
+                else -> ContentLoadingErrorState.Content
+            }
+        }
 
-        LazyColumn(
-            modifier = Modifier
-                .fillMaxSize()
-                .imePadding(),
-            verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.double, Alignment.CenterVertically),
+        ContentLoadingErrorView(
+            state = cleState,
+            loading = {
+                LoadingView(
+                    message = stringResource(id = R.string.account_setup_auto_discovery_loading_message),
+                    modifier = Modifier.fillMaxSize(),
+                )
+            },
+            error = {
+                ErrorView(
+                    title = stringResource(id = R.string.account_setup_auto_discovery_loading_error),
+                    message = state.error?.toResourceString(resources),
+                    onRetry = { onEvent(Event.OnRetryClicked) },
+                    modifier = Modifier.fillMaxSize(),
+                )
+            },
         ) {
-            if (state.isLoading) {
-                item(key = "loading") {
-                    LoadingItem(
-                        message = stringResource(id = R.string.account_setup_auto_discovery_loading_message),
-                    )
-                }
-            } else if (state.error != null) {
-                item(key = "error") {
-                    ErrorItem(
-                        title = stringResource(id = R.string.account_setup_auto_discovery_loading_error),
-                        message = state.error.toResourceString(resources),
-                        onRetry = { onEvent(Event.OnRetryClicked) },
-                    )
-                }
-            } else {
+            LazyColumn(
+                modifier = Modifier
+                    .fillMaxSize()
+                    .imePadding(),
+                verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.double, Alignment.CenterVertically),
+            ) {
                 contentItems(
                     state = state,
                     onEvent = onEvent,
-- 
GitLab


From c99674b42fa96dd94378ff14444e8c9e61ccf4c3 Mon Sep 17 00:00:00 2001
From: Thomas Braccia 
Date: Wed, 20 Sep 2023 10:21:27 -0400
Subject: [PATCH 58/94] feat: added content description for overflow

---
 app/ui/legacy/src/main/res/layout/message_view_header.xml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/ui/legacy/src/main/res/layout/message_view_header.xml b/app/ui/legacy/src/main/res/layout/message_view_header.xml
index ff2bb043b3..ea9a2436c1 100644
--- a/app/ui/legacy/src/main/res/layout/message_view_header.xml
+++ b/app/ui/legacy/src/main/res/layout/message_view_header.xml
@@ -165,6 +165,7 @@
             android:layout_marginBottom="16dp"
             android:background="?attr/controlBackground"
             android:clickable="true"
+            android:contentDescription="@string/abc_action_menu_overflow_description"
             android:focusable="true"
             android:paddingStart="6dp"
             android:paddingEnd="10dp"
-- 
GitLab


From 72085c132f0ebda86b2c07bf47d52d34fe4d5e76 Mon Sep 17 00:00:00 2001
From: Thomas Braccia 
Date: Wed, 20 Sep 2023 10:25:42 -0400
Subject: [PATCH 59/94] feat: added content description for reply button

---
 app/ui/legacy/src/main/res/layout/message_view_header.xml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/ui/legacy/src/main/res/layout/message_view_header.xml b/app/ui/legacy/src/main/res/layout/message_view_header.xml
index ff2bb043b3..9018b08245 100644
--- a/app/ui/legacy/src/main/res/layout/message_view_header.xml
+++ b/app/ui/legacy/src/main/res/layout/message_view_header.xml
@@ -152,6 +152,7 @@
             android:layout_width="48dp"
             android:layout_height="48dp"
             android:background="?attr/controlBackground"
+            android:contentDescription="@string/reply_action"
             android:paddingHorizontal="12dp"
             app:layout_constraintEnd_toStartOf="@id/menu_overflow"
             app:layout_constraintTop_toTopOf="@+id/menu_overflow"
-- 
GitLab


From abce7d0f311a549c570028492571e3c1b51016ab Mon Sep 17 00:00:00 2001
From: cketti 
Date: Thu, 21 Sep 2023 15:45:27 +0200
Subject: [PATCH 60/94] Use deep links with FeatureLauncherActivity

---
 .../setup/navigation/AccountSetupNavigation.kt  |  9 ++++++++-
 .../feature/launcher/FeatureLauncherActivity.kt | 17 ++++++-----------
 .../navigation/FeatureLauncherNavHost.kt        |  3 +--
 .../feature/launcher/ui/FeatureLauncherApp.kt   |  2 --
 .../navigation/OnboardingNavigation.kt          |  9 ++++++++-
 5 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt
index a4e95c1fdf..7bc254aa51 100644
--- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt
+++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt
@@ -4,9 +4,11 @@ import androidx.navigation.NavController
 import androidx.navigation.NavGraphBuilder
 import androidx.navigation.NavOptions
 import androidx.navigation.compose.composable
+import androidx.navigation.navDeepLink
 import app.k9mail.feature.account.setup.ui.AccountSetupScreen
 
 const val NAVIGATION_ROUTE_ACCOUNT_SETUP = "/account/setup"
+const val DEEPLINK_ACCOUNT_SETUP = "app://$NAVIGATION_ROUTE_ACCOUNT_SETUP"
 
 fun NavController.navigateToAccountSetup(navOptions: NavOptions? = null) {
     navigate(NAVIGATION_ROUTE_ACCOUNT_SETUP, navOptions)
@@ -16,7 +18,12 @@ fun NavGraphBuilder.accountSetupRoute(
     onBack: () -> Unit,
     onFinish: (String) -> Unit,
 ) {
-    composable(route = NAVIGATION_ROUTE_ACCOUNT_SETUP) {
+    composable(
+        route = NAVIGATION_ROUTE_ACCOUNT_SETUP,
+        deepLinks = listOf(
+            navDeepLink { uriPattern = DEEPLINK_ACCOUNT_SETUP },
+        ),
+    ) {
         AccountSetupScreen(
             onBack = onBack,
             onFinish = onFinish,
diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt
index fe1be03d4c..1dc3bd431e 100644
--- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt
+++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt
@@ -4,11 +4,12 @@ import android.app.Activity
 import android.content.Intent
 import android.os.Bundle
 import androidx.activity.ComponentActivity
+import androidx.core.net.toUri
 import androidx.core.view.WindowCompat
 import app.k9mail.core.ui.compose.common.activity.setActivityContent
-import app.k9mail.feature.account.setup.navigation.NAVIGATION_ROUTE_ACCOUNT_SETUP
+import app.k9mail.feature.account.setup.navigation.DEEPLINK_ACCOUNT_SETUP
 import app.k9mail.feature.launcher.ui.FeatureLauncherApp
-import app.k9mail.feature.onboarding.navigation.NAVIGATION_ROUTE_ONBOARDING
+import app.k9mail.feature.onboarding.navigation.DEEPLINK_ONBOARDING
 
 class FeatureLauncherActivity : ComponentActivity() {
 
@@ -17,22 +18,16 @@ class FeatureLauncherActivity : ComponentActivity() {
 
         WindowCompat.setDecorFitsSystemWindows(window, false)
 
-        val destination = intent.getStringExtra(EXTRA_DESTINATION)
-
         setActivityContent {
-            FeatureLauncherApp(startDestination = destination)
+            FeatureLauncherApp()
         }
     }
 
     companion object {
-        private const val EXTRA_DESTINATION = "destination"
-        private const val DESTINATION_ONBOARDING = NAVIGATION_ROUTE_ONBOARDING
-        private const val DESTINATION_SETUP_ACCOUNT = NAVIGATION_ROUTE_ACCOUNT_SETUP
-
         @JvmStatic
         fun launchOnboarding(context: Activity) {
             val intent = Intent(context, FeatureLauncherActivity::class.java).apply {
-                putExtra(EXTRA_DESTINATION, DESTINATION_ONBOARDING)
+                data = DEEPLINK_ONBOARDING.toUri()
                 flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
             }
             context.startActivity(intent)
@@ -41,7 +36,7 @@ class FeatureLauncherActivity : ComponentActivity() {
         @JvmStatic
         fun launchSetupAccount(context: Activity) {
             val intent = Intent(context, FeatureLauncherActivity::class.java).apply {
-                putExtra(EXTRA_DESTINATION, DESTINATION_SETUP_ACCOUNT)
+                data = DEEPLINK_ACCOUNT_SETUP.toUri()
             }
             context.startActivity(intent)
         }
diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt
index a5b78510fe..2faec3562e 100644
--- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt
+++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt
@@ -15,7 +15,6 @@ import org.koin.compose.koinInject
 @Composable
 fun FeatureLauncherNavHost(
     navController: NavHostController,
-    startDestination: String?,
     onBack: () -> Unit,
     modifier: Modifier = Modifier,
     importSettingsLauncher: ImportSettingsLauncher = koinInject(),
@@ -23,7 +22,7 @@ fun FeatureLauncherNavHost(
 ) {
     NavHost(
         navController = navController,
-        startDestination = startDestination ?: NAVIGATION_ROUTE_ONBOARDING,
+        startDestination = NAVIGATION_ROUTE_ONBOARDING,
         modifier = modifier,
     ) {
         onboardingRoute(
diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt
index 0bafc94ec0..27aef780a5 100644
--- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt
+++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt
@@ -12,7 +12,6 @@ import app.k9mail.feature.launcher.navigation.FeatureLauncherNavHost
 
 @Composable
 fun FeatureLauncherApp(
-    startDestination: String?,
     modifier: Modifier = Modifier,
 ) {
     val navController = rememberNavController()
@@ -28,7 +27,6 @@ fun FeatureLauncherApp(
 
             FeatureLauncherNavHost(
                 navController = navController,
-                startDestination = startDestination,
                 onBack = { activity.finish() },
             )
         }
diff --git a/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt b/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt
index 86a700e1bb..c64ef759bc 100644
--- a/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt
+++ b/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt
@@ -4,9 +4,11 @@ import androidx.navigation.NavController
 import androidx.navigation.NavGraphBuilder
 import androidx.navigation.NavOptions
 import androidx.navigation.compose.composable
+import androidx.navigation.navDeepLink
 import app.k9mail.feature.onboarding.ui.OnboardingScreen
 
 const val NAVIGATION_ROUTE_ONBOARDING = "/onboarding"
+const val DEEPLINK_ONBOARDING = "app://$NAVIGATION_ROUTE_ONBOARDING"
 
 fun NavController.navigateToOnboarding(
     navOptions: NavOptions? = null,
@@ -18,7 +20,12 @@ fun NavGraphBuilder.onboardingRoute(
     onStart: () -> Unit,
     onImport: () -> Unit,
 ) {
-    composable(route = NAVIGATION_ROUTE_ONBOARDING) {
+    composable(
+        route = NAVIGATION_ROUTE_ONBOARDING,
+        deepLinks = listOf(
+            navDeepLink { uriPattern = DEEPLINK_ONBOARDING },
+        ),
+    ) {
         OnboardingScreen(
             onStartClick = onStart,
             onImportClick = onImport,
-- 
GitLab


From 5afd7b70b32fc82019b0d3cd94d13bff6a407db2 Mon Sep 17 00:00:00 2001
From: cketti 
Date: Thu, 21 Sep 2023 15:56:34 +0200
Subject: [PATCH 61/94] Add helpers for creating deep link-enabled navigation
 destinations

---
 .../common/navigation/NavigationExtensions.kt | 30 +++++++++++++++++++
 .../navigation/AccountSetupNavigation.kt      | 11 ++-----
 .../launcher/FeatureLauncherActivity.kt       | 10 +++----
 .../navigation/OnboardingNavigation.kt        | 11 ++-----
 4 files changed, 39 insertions(+), 23 deletions(-)
 create mode 100644 core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/navigation/NavigationExtensions.kt

diff --git a/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/navigation/NavigationExtensions.kt b/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/navigation/NavigationExtensions.kt
new file mode 100644
index 0000000000..bce88f0686
--- /dev/null
+++ b/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/navigation/NavigationExtensions.kt
@@ -0,0 +1,30 @@
+package app.k9mail.core.ui.compose.common.navigation
+
+import android.net.Uri
+import androidx.compose.animation.AnimatedContentScope
+import androidx.compose.runtime.Composable
+import androidx.core.net.toUri
+import androidx.navigation.NamedNavArgument
+import androidx.navigation.NavBackStackEntry
+import androidx.navigation.NavGraphBuilder
+import androidx.navigation.compose.composable
+import androidx.navigation.navDeepLink
+
+fun NavGraphBuilder.deepLinkComposable(
+    route: String,
+    arguments: List = emptyList(),
+    content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit,
+) {
+    composable(
+        route = route,
+        arguments = arguments,
+        deepLinks = listOf(
+            navDeepLink { uriPattern = route.toDeepLink() },
+        ),
+        content = content,
+    )
+}
+
+fun String.toDeepLink(): String = "app://$this"
+
+fun String.toDeepLinkUri(): Uri = toDeepLink().toUri()
diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt
index 7bc254aa51..f2565b783f 100644
--- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt
+++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt
@@ -3,12 +3,10 @@ package app.k9mail.feature.account.setup.navigation
 import androidx.navigation.NavController
 import androidx.navigation.NavGraphBuilder
 import androidx.navigation.NavOptions
-import androidx.navigation.compose.composable
-import androidx.navigation.navDeepLink
+import app.k9mail.core.ui.compose.common.navigation.deepLinkComposable
 import app.k9mail.feature.account.setup.ui.AccountSetupScreen
 
 const val NAVIGATION_ROUTE_ACCOUNT_SETUP = "/account/setup"
-const val DEEPLINK_ACCOUNT_SETUP = "app://$NAVIGATION_ROUTE_ACCOUNT_SETUP"
 
 fun NavController.navigateToAccountSetup(navOptions: NavOptions? = null) {
     navigate(NAVIGATION_ROUTE_ACCOUNT_SETUP, navOptions)
@@ -18,12 +16,7 @@ fun NavGraphBuilder.accountSetupRoute(
     onBack: () -> Unit,
     onFinish: (String) -> Unit,
 ) {
-    composable(
-        route = NAVIGATION_ROUTE_ACCOUNT_SETUP,
-        deepLinks = listOf(
-            navDeepLink { uriPattern = DEEPLINK_ACCOUNT_SETUP },
-        ),
-    ) {
+    deepLinkComposable(route = NAVIGATION_ROUTE_ACCOUNT_SETUP) {
         AccountSetupScreen(
             onBack = onBack,
             onFinish = onFinish,
diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt
index 1dc3bd431e..df0df6ca39 100644
--- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt
+++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt
@@ -4,12 +4,12 @@ import android.app.Activity
 import android.content.Intent
 import android.os.Bundle
 import androidx.activity.ComponentActivity
-import androidx.core.net.toUri
 import androidx.core.view.WindowCompat
 import app.k9mail.core.ui.compose.common.activity.setActivityContent
-import app.k9mail.feature.account.setup.navigation.DEEPLINK_ACCOUNT_SETUP
+import app.k9mail.core.ui.compose.common.navigation.toDeepLinkUri
+import app.k9mail.feature.account.setup.navigation.NAVIGATION_ROUTE_ACCOUNT_SETUP
 import app.k9mail.feature.launcher.ui.FeatureLauncherApp
-import app.k9mail.feature.onboarding.navigation.DEEPLINK_ONBOARDING
+import app.k9mail.feature.onboarding.navigation.NAVIGATION_ROUTE_ONBOARDING
 
 class FeatureLauncherActivity : ComponentActivity() {
 
@@ -27,7 +27,7 @@ class FeatureLauncherActivity : ComponentActivity() {
         @JvmStatic
         fun launchOnboarding(context: Activity) {
             val intent = Intent(context, FeatureLauncherActivity::class.java).apply {
-                data = DEEPLINK_ONBOARDING.toUri()
+                data = NAVIGATION_ROUTE_ONBOARDING.toDeepLinkUri()
                 flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
             }
             context.startActivity(intent)
@@ -36,7 +36,7 @@ class FeatureLauncherActivity : ComponentActivity() {
         @JvmStatic
         fun launchSetupAccount(context: Activity) {
             val intent = Intent(context, FeatureLauncherActivity::class.java).apply {
-                data = DEEPLINK_ACCOUNT_SETUP.toUri()
+                data = NAVIGATION_ROUTE_ACCOUNT_SETUP.toDeepLinkUri()
             }
             context.startActivity(intent)
         }
diff --git a/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt b/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt
index c64ef759bc..f146364956 100644
--- a/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt
+++ b/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt
@@ -3,12 +3,10 @@ package app.k9mail.feature.onboarding.navigation
 import androidx.navigation.NavController
 import androidx.navigation.NavGraphBuilder
 import androidx.navigation.NavOptions
-import androidx.navigation.compose.composable
-import androidx.navigation.navDeepLink
+import app.k9mail.core.ui.compose.common.navigation.deepLinkComposable
 import app.k9mail.feature.onboarding.ui.OnboardingScreen
 
 const val NAVIGATION_ROUTE_ONBOARDING = "/onboarding"
-const val DEEPLINK_ONBOARDING = "app://$NAVIGATION_ROUTE_ONBOARDING"
 
 fun NavController.navigateToOnboarding(
     navOptions: NavOptions? = null,
@@ -20,12 +18,7 @@ fun NavGraphBuilder.onboardingRoute(
     onStart: () -> Unit,
     onImport: () -> Unit,
 ) {
-    composable(
-        route = NAVIGATION_ROUTE_ONBOARDING,
-        deepLinks = listOf(
-            navDeepLink { uriPattern = DEEPLINK_ONBOARDING },
-        ),
-    ) {
+    deepLinkComposable(route = NAVIGATION_ROUTE_ONBOARDING) {
         OnboardingScreen(
             onStartClick = onStart,
             onImportClick = onImport,
-- 
GitLab


From 5b00628fe6528b8475ab1001bb8b4820095b97c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Tue, 19 Sep 2023 11:41:18 +0200
Subject: [PATCH 62/94] Wrap ErrorView and LoadingView in a box to be able to
 scale them to fillSize without changing their content size

---
 .../catalog/ui/molecule/items/StateItems.kt   |  2 +-
 .../molecule/ContentLoadingErrorView.kt       | 10 +--
 .../designsystem/molecule/ErrorView.kt        | 78 ++++++++++---------
 .../designsystem/molecule/LoadingView.kt      | 31 +++++---
 .../AccountAutoDiscoveryContent.kt            |  4 +-
 5 files changed, 71 insertions(+), 54 deletions(-)

diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/molecule/items/StateItems.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/molecule/items/StateItems.kt
index ad3d56081e..82231091d1 100644
--- a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/molecule/items/StateItems.kt
+++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/molecule/items/StateItems.kt
@@ -61,7 +61,7 @@ fun LazyGridScope.stateItems() {
 @Composable
 private fun StatefulContentLoadingErrorState() {
     val state = remember {
-        mutableStateOf(ContentLoadingErrorState.Loading)
+        mutableStateOf(ContentLoadingErrorState.Loading)
     }
 
     ContentLoadingErrorView(
diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ContentLoadingErrorView.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ContentLoadingErrorView.kt
index f1d7f82a9f..3985665b85 100644
--- a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ContentLoadingErrorView.kt
+++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ContentLoadingErrorView.kt
@@ -30,7 +30,7 @@ fun ContentLoadingErrorView(
     ) {
         AnimatedContent(
             targetState = state,
-            label = "CleView",
+            label = "ContentLoadingErrorView",
         ) { targetState ->
             when (targetState) {
                 ContentLoadingErrorState.Loading -> loading()
@@ -41,10 +41,8 @@ fun ContentLoadingErrorView(
     }
 }
 
-sealed interface ContentLoadingErrorState {
-    object Loading : ContentLoadingErrorState
-    object Content : ContentLoadingErrorState
-    object Error : ContentLoadingErrorState
+enum class ContentLoadingErrorState {
+    Loading, Content, Error
 }
 
 @Composable
@@ -52,7 +50,7 @@ sealed interface ContentLoadingErrorState {
 internal fun ContentLoadingErrorViewPreview() {
     PreviewWithThemes {
         val state = remember {
-            mutableStateOf(ContentLoadingErrorState.Loading)
+            mutableStateOf(ContentLoadingErrorState.Loading)
         }
 
         ContentLoadingErrorView(
diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ErrorView.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ErrorView.kt
index 54f7d38c31..d60281fcef 100644
--- a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ErrorView.kt
+++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/ErrorView.kt
@@ -1,6 +1,7 @@
 package app.k9mail.core.ui.compose.designsystem.molecule
 
 import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -26,49 +27,56 @@ fun ErrorView(
     modifier: Modifier = Modifier,
     message: String? = null,
     onRetry: () -> Unit = { },
+    contentAlignment: Alignment = Alignment.Center,
 ) {
-    Column(
+    Box(
         modifier = Modifier
             .fillMaxWidth()
-            .padding(
-                vertical = MainTheme.spacings.default,
-                horizontal = MainTheme.spacings.double,
-            )
             .then(modifier),
-        horizontalAlignment = Alignment.CenterHorizontally,
-        verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
+        contentAlignment = contentAlignment,
     ) {
-        Icon(
-            imageVector = Icons.Filled.error,
-            contentDescription = null,
-            tint = MainTheme.colors.error,
-            modifier = Modifier.padding(top = MainTheme.spacings.default),
-        )
-        TextSubtitle1(
-            text = title,
-            modifier = Modifier.padding(bottom = MainTheme.spacings.default),
-        )
-        if (message != null) {
-            TextBody2(
-                text = message,
-                modifier = Modifier
-                    .fillMaxWidth(),
-            )
-        }
-        Row(
+        Column(
             modifier = Modifier
-                .fillMaxWidth(),
-            verticalAlignment = Alignment.CenterVertically,
-            horizontalArrangement = Arrangement.End,
-        ) {
-            ButtonText(
-                text = stringResource(id = R.string.designsystem_molecule_error_view_button_retry),
-                onClick = onRetry,
-                contentPadding = buttonContentPadding(
-                    start = MainTheme.spacings.double,
-                    end = MainTheme.spacings.double,
+                .fillMaxWidth()
+                .padding(
+                    vertical = MainTheme.spacings.default,
+                    horizontal = MainTheme.spacings.double,
                 ),
+            horizontalAlignment = Alignment.CenterHorizontally,
+            verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
+        ) {
+            Icon(
+                imageVector = Icons.Filled.error,
+                contentDescription = null,
+                tint = MainTheme.colors.error,
+                modifier = Modifier.padding(top = MainTheme.spacings.default),
             )
+            TextSubtitle1(
+                text = title,
+                modifier = Modifier.padding(bottom = MainTheme.spacings.default),
+            )
+            if (message != null) {
+                TextBody2(
+                    text = message,
+                    modifier = Modifier
+                        .fillMaxWidth(),
+                )
+            }
+            Row(
+                modifier = Modifier
+                    .fillMaxWidth(),
+                verticalAlignment = Alignment.CenterVertically,
+                horizontalArrangement = Arrangement.End,
+            ) {
+                ButtonText(
+                    text = stringResource(id = R.string.designsystem_molecule_error_view_button_retry),
+                    onClick = onRetry,
+                    contentPadding = buttonContentPadding(
+                        start = MainTheme.spacings.double,
+                        end = MainTheme.spacings.double,
+                    ),
+                )
+            }
         }
     }
 }
diff --git a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/LoadingView.kt b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/LoadingView.kt
index cb799625b5..3266398109 100644
--- a/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/LoadingView.kt
+++ b/core/ui/compose/designsystem/src/main/kotlin/app/k9mail/core/ui/compose/designsystem/molecule/LoadingView.kt
@@ -1,5 +1,7 @@
 package app.k9mail.core.ui.compose.designsystem.molecule
 
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -18,22 +20,31 @@ import app.k9mail.core.ui.compose.theme.PreviewWithThemes
 fun LoadingView(
     modifier: Modifier = Modifier,
     message: String? = null,
+    contentAlignment: Alignment = Alignment.Center,
 ) {
-    Column(
+    Box(
         modifier = Modifier
             .fillMaxWidth()
-            .padding(MainTheme.spacings.default)
             .then(modifier),
-        horizontalAlignment = Alignment.CenterHorizontally,
+        contentAlignment = contentAlignment,
     ) {
-        if (message != null) {
-            TextSubtitle1(text = message)
-        }
-        Row(
-            modifier = Modifier.height(MainTheme.sizes.larger),
-            verticalAlignment = Alignment.CenterVertically,
+        Column(
+            modifier = Modifier
+                .fillMaxWidth()
+                .padding(MainTheme.spacings.default)
+                .then(modifier),
+            horizontalAlignment = Alignment.CenterHorizontally,
+            verticalArrangement = Arrangement.Center,
         ) {
-            CircularProgressIndicator()
+            if (message != null) {
+                TextSubtitle1(text = message)
+            }
+            Row(
+                modifier = Modifier.height(MainTheme.sizes.larger),
+                verticalAlignment = Alignment.CenterVertically,
+            ) {
+                CircularProgressIndicator()
+            }
         }
     }
 }
diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt
index ef1587a180..1b1a48b883 100644
--- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt
+++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/autodiscovery/AccountAutoDiscoveryContent.kt
@@ -46,7 +46,7 @@ internal fun AccountAutoDiscoveryContent(
             .then(modifier),
     ) {
         val resources = LocalContext.current.resources
-        val cleState = remember(key1 = state.isLoading, key2 = state.error) {
+        val viewState = remember(key1 = state.isLoading, key2 = state.error) {
             when {
                 state.isLoading -> ContentLoadingErrorState.Loading
                 state.error != null -> ContentLoadingErrorState.Error
@@ -55,7 +55,7 @@ internal fun AccountAutoDiscoveryContent(
         }
 
         ContentLoadingErrorView(
-            state = cleState,
+            state = viewState,
             loading = {
                 LoadingView(
                     message = stringResource(id = R.string.account_setup_auto_discovery_loading_message),
-- 
GitLab


From 4ec59a881d1c1ece17b7ac065d75d94ae22b73a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Fri, 22 Sep 2023 13:52:40 +0200
Subject: [PATCH 63/94] Fix OAuth 2 for Yahoo and AOL as they only support
 Authorization Code with PKCE now

---
 .../feature/account/oauth/data/AuthorizationRepository.kt    | 5 ++++-
 .../account/oauth/data/AuthorizationRepositoryTest.kt        | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepository.kt b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepository.kt
index 0cbba30156..882ac1780c 100644
--- a/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepository.kt
+++ b/feature/account/oauth/src/main/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepository.kt
@@ -14,6 +14,7 @@ import net.openid.appauth.AuthorizationRequest
 import net.openid.appauth.AuthorizationResponse
 import net.openid.appauth.AuthorizationService
 import net.openid.appauth.AuthorizationServiceConfiguration
+import net.openid.appauth.CodeVerifierUtil
 import net.openid.appauth.ResponseTypeValues
 import timber.log.Timber
 
@@ -80,9 +81,11 @@ class AuthorizationRepository(
             configuration.redirectUri.toUri(),
         )
 
+        val codeVerifier = CodeVerifierUtil.generateRandomCodeVerifier()
+
         val authRequest = authRequestBuilder
             .setScope(configuration.scopes.joinToString(" "))
-            .setCodeVerifier(null)
+            .setCodeVerifier(codeVerifier)
             .setLoginHint(emailAddress)
             .build()
 
diff --git a/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepositoryTest.kt b/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepositoryTest.kt
index 78cce14918..6ebcf370a6 100644
--- a/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepositoryTest.kt
+++ b/feature/account/oauth/src/test/kotlin/app/k9mail/feature/account/oauth/data/AuthorizationRepositoryTest.kt
@@ -9,6 +9,7 @@ import app.k9mail.feature.account.oauth.domain.entity.AuthorizationResult
 import assertk.all
 import assertk.assertThat
 import assertk.assertions.isEqualTo
+import assertk.assertions.isNotEmpty
 import assertk.assertions.isNotNull
 import assertk.assertions.isNull
 import assertk.assertions.prop
@@ -72,8 +73,10 @@ class AuthorizationRepositoryTest {
                 prop(AuthorizationRequest::responseType).isEqualTo(ResponseTypeValues.CODE)
                 prop(AuthorizationRequest::redirectUri).isEqualTo(oAuthConfiguration.redirectUri.toUri())
                 prop(AuthorizationRequest::scope).isEqualTo("scope scope2")
-                prop(AuthorizationRequest::codeVerifier).isNull()
                 prop(AuthorizationRequest::loginHint).isEqualTo(emailAddress)
+                prop(AuthorizationRequest::codeVerifier).isNotNull()
+                prop(AuthorizationRequest::codeVerifierChallengeMethod).isEqualTo("S256")
+                prop(AuthorizationRequest::codeVerifierChallenge).isNotNull().isNotEmpty()
             }
         }
 
-- 
GitLab


From 9fc8dffd2d0f3e53e72e99bb02e20dc8e159922e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Fri, 22 Sep 2023 17:44:18 +0200
Subject: [PATCH 64/94] Remove AccountSetupNames

---
 app/k9mail/src/main/AndroidManifest.xml       |   5 -
 .../k9/activity/setup/AccountSetupBasics.kt   |   2 +-
 .../k9/activity/setup/AccountSetupNames.java  | 102 ------------------
 .../activity/setup/AccountSetupOptions.java   |   2 +-
 .../main/res/layout/account_setup_names.xml   |  59 ----------
 .../legacy/src/main/res/values-ar/strings.xml |   3 -
 .../legacy/src/main/res/values-be/strings.xml |   3 -
 .../legacy/src/main/res/values-bg/strings.xml |   3 -
 .../legacy/src/main/res/values-br/strings.xml |   3 -
 .../legacy/src/main/res/values-ca/strings.xml |   3 -
 .../legacy/src/main/res/values-cs/strings.xml |   3 -
 .../legacy/src/main/res/values-cy/strings.xml |   3 -
 .../legacy/src/main/res/values-da/strings.xml |   3 -
 .../legacy/src/main/res/values-de/strings.xml |   3 -
 .../legacy/src/main/res/values-el/strings.xml |   3 -
 .../legacy/src/main/res/values-eo/strings.xml |   3 -
 .../legacy/src/main/res/values-es/strings.xml |   3 -
 .../legacy/src/main/res/values-et/strings.xml |   3 -
 .../legacy/src/main/res/values-eu/strings.xml |   3 -
 .../legacy/src/main/res/values-fa/strings.xml |   3 -
 .../legacy/src/main/res/values-fi/strings.xml |   3 -
 .../legacy/src/main/res/values-fr/strings.xml |   3 -
 .../legacy/src/main/res/values-fy/strings.xml |   3 -
 .../legacy/src/main/res/values-gd/strings.xml |   3 -
 .../legacy/src/main/res/values-gl/strings.xml |   3 -
 .../legacy/src/main/res/values-hr/strings.xml |   3 -
 .../legacy/src/main/res/values-hu/strings.xml |   3 -
 .../legacy/src/main/res/values-in/strings.xml |   3 -
 .../legacy/src/main/res/values-is/strings.xml |   3 -
 .../legacy/src/main/res/values-it/strings.xml |   3 -
 .../legacy/src/main/res/values-iw/strings.xml |   3 -
 .../legacy/src/main/res/values-ja/strings.xml |   3 -
 .../legacy/src/main/res/values-ko/strings.xml |   3 -
 .../legacy/src/main/res/values-lt/strings.xml |   3 -
 .../legacy/src/main/res/values-lv/strings.xml |   3 -
 .../legacy/src/main/res/values-ml/strings.xml |   3 -
 .../legacy/src/main/res/values-nb/strings.xml |   3 -
 .../legacy/src/main/res/values-nl/strings.xml |   3 -
 .../legacy/src/main/res/values-pl/strings.xml |   3 -
 .../src/main/res/values-pt-rBR/strings.xml    |   3 -
 .../src/main/res/values-pt-rPT/strings.xml    |   3 -
 .../legacy/src/main/res/values-ro/strings.xml |   3 -
 .../legacy/src/main/res/values-ru/strings.xml |   3 -
 .../legacy/src/main/res/values-sk/strings.xml |   3 -
 .../legacy/src/main/res/values-sl/strings.xml |   3 -
 .../legacy/src/main/res/values-sq/strings.xml |   3 -
 .../legacy/src/main/res/values-sr/strings.xml |   3 -
 .../legacy/src/main/res/values-sv/strings.xml |   3 -
 .../legacy/src/main/res/values-tr/strings.xml |   3 -
 .../legacy/src/main/res/values-uk/strings.xml |   3 -
 .../src/main/res/values-zh-rCN/strings.xml    |   3 -
 .../src/main/res/values-zh-rTW/strings.xml    |   3 -
 app/ui/legacy/src/main/res/values/strings.xml |   4 -
 53 files changed, 2 insertions(+), 313 deletions(-)
 delete mode 100644 app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupNames.java
 delete mode 100644 app/ui/legacy/src/main/res/layout/account_setup_names.xml

diff --git a/app/k9mail/src/main/AndroidManifest.xml b/app/k9mail/src/main/AndroidManifest.xml
index 1d0d83d85d..69b476f9a7 100644
--- a/app/k9mail/src/main/AndroidManifest.xml
+++ b/app/k9mail/src/main/AndroidManifest.xml
@@ -100,11 +100,6 @@
             android:configChanges="locale"
             android:label="@string/account_setup_options_title"/>
 
-        
-
         
-
-
-    
-
-    
-
-        
-
-            
-
-                
-            
-
-            
-
-                
-            
-
-            
-        
-    
-
-    
-
diff --git a/app/ui/legacy/src/main/res/values-ar/strings.xml b/app/ui/legacy/src/main/res/values-ar/strings.xml
index b6402c336e..9facad5b5e 100644
--- a/app/ui/legacy/src/main/res/values-ar/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ar/strings.xml
@@ -339,9 +339,6 @@
   المصادقة \u2026
   إحضار إعدادات الحساب ... 
   جارٍ الإلغاء\u2026
-  لقد انتهيت تقريبًا
-  اَعطِ هذا الحساب اسمًا (اختياري):
-  اكتب اسمك (تظهر في الرسائل الصادرة):
   نوع الحساب
   ما نوع هذا الحساب؟
   POP3
diff --git a/app/ui/legacy/src/main/res/values-be/strings.xml b/app/ui/legacy/src/main/res/values-be/strings.xml
index d911c337b7..926e686e8c 100644
--- a/app/ui/legacy/src/main/res/values-be/strings.xml
+++ b/app/ui/legacy/src/main/res/values-be/strings.xml
@@ -334,9 +334,6 @@ K-9 Mail - шматфункцыянальны свабодны паштовы к
   Аўтэнтыфікацыя\u2026
   Атрыманне налад акаўнта\u2026
   Скасаванне\u2026
-  Амаль завершана!
-  Даць акаўнту назву (неабавязкова):
-  Ваша імя (бачна адрасату):
   Тып акаўнта
   Што гэта за акаўнт?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-bg/strings.xml b/app/ui/legacy/src/main/res/values-bg/strings.xml
index 3ed5906e50..24d707fd2a 100644
--- a/app/ui/legacy/src/main/res/values-bg/strings.xml
+++ b/app/ui/legacy/src/main/res/values-bg/strings.xml
@@ -299,9 +299,6 @@ K-9 Mail е мощен, безплатен имейл клиент за Андр
   Идентифициране\u2026
   Получава настройките на профила\u2026
   Отказва\u2026
-  Почти проключихте!
-  Дайте име на профила (незадължително):
-  Въведете вашето име (ще се показва в изходящите съобщения):
   Тип на профила
   Какъв тип профил е това?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-br/strings.xml b/app/ui/legacy/src/main/res/values-br/strings.xml
index 870dbdc52f..b60cc1a72a 100644
--- a/app/ui/legacy/src/main/res/values-br/strings.xml
+++ b/app/ui/legacy/src/main/res/values-br/strings.xml
@@ -280,9 +280,6 @@ Danevellit beugoù, kenlabourit war keweriusterioù nevez ha savit goulennoù wa
   Dilesa\u2026
   O kerc’hat arventennoù ar gont\u2026
   O nullañ\u2026
-  Tost echu!
-  Roit un anv d’ar gont-mañ (diret):
-  Skrivit hoc’h anv (diskouezet e vo er c’hemennadennoù kaset):
   Doare kont
   Peseurt doare kont eo?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-ca/strings.xml b/app/ui/legacy/src/main/res/values-ca/strings.xml
index a66df5e25a..4ccf034fdc 100644
--- a/app/ui/legacy/src/main/res/values-ca/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ca/strings.xml
@@ -331,9 +331,6 @@ Si us plau, envieu informes d\'errors, contribuïu-hi amb noves millores i feu p
   S\'està autenticant\u2026
   S\'està recuperant la configuració del compte\u2026
   S\'està cancel·lant\u2026
-  Ja gairebé hem acabat!
-  Dóna un nom a aquest compte (opcional):
-  Escriviu el nom (és el que es mostrarà als missatges sortints):
   Tipus de compte
   Quin tipus de compte és?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-cs/strings.xml b/app/ui/legacy/src/main/res/values-cs/strings.xml
index 74353d631c..56148e3102 100644
--- a/app/ui/legacy/src/main/res/values-cs/strings.xml
+++ b/app/ui/legacy/src/main/res/values-cs/strings.xml
@@ -335,9 +335,6 @@ Hlášení o chyb, úpravy pro nové funkce a dotazy zadávejte prostřednictví
   Přihlašuji se\u2026
   Stahuji nastavení účtu\u2026
   Rušení\u2026
-  Téměř hotovo!
-  Pojmenujte tento účet (volitelné):
-  Zadejte své jméno (zobrazuje se v odchozích zprávách):
   Typ účtu
   O jaký typ účtu jde?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-cy/strings.xml b/app/ui/legacy/src/main/res/values-cy/strings.xml
index bef2373585..78f231d9e8 100644
--- a/app/ui/legacy/src/main/res/values-cy/strings.xml
+++ b/app/ui/legacy/src/main/res/values-cy/strings.xml
@@ -322,9 +322,6 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
   Yn dilysu\u2026
   Yn nôl gosodiadau\'r cyfrif\u2026
   Yn diddymu\u2026
-  Bron a gorffen!
-  Rhoi enw i\'r cyfrif hwn (dim yn ofynnol):
-  Dy enw (i\'w weld ar negeseuon sy\'n cael eu hanfon):
   Math o gyfrif
   Pa fath o gyfrif ydy hwn?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-da/strings.xml b/app/ui/legacy/src/main/res/values-da/strings.xml
index 4be83125be..0be62f47b6 100644
--- a/app/ui/legacy/src/main/res/values-da/strings.xml
+++ b/app/ui/legacy/src/main/res/values-da/strings.xml
@@ -326,9 +326,6 @@ Rapporter venligst fejl, forslag til nye funktioner eller stil spørgsmål på:
   Autentiserer\u2026
   Henter kontoindstillinger\u2026
   Afbryder\u2026
-  Næsten færdig!
-  Giv denne konto et navn (frivilligt):
-  Indtast dit navn (vises på udgående mails):
   Kontotype
   Hvilken type konto er dette?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-de/strings.xml b/app/ui/legacy/src/main/res/values-de/strings.xml
index d92749bb73..e77b07a072 100644
--- a/app/ui/legacy/src/main/res/values-de/strings.xml
+++ b/app/ui/legacy/src/main/res/values-de/strings.xml
@@ -330,9 +330,6 @@ Bitte sende Fehlerberichte, Ideen für neue Funktionen und stelle Fragen an
   Authentifizierung\u2026
   Kontoeinstellungen werden geladen\u2026
   Aktion wird abgebrochen\u2026
-  Fast fertig!
-  Kontoname (optional):
-  Dein Name (Anzeige bei ausgehenden Nachrichten):
   Kontotyp
   Art des Kontos?
   POP3-Konto
diff --git a/app/ui/legacy/src/main/res/values-el/strings.xml b/app/ui/legacy/src/main/res/values-el/strings.xml
index 6c00cd1fb7..396b95a4a9 100644
--- a/app/ui/legacy/src/main/res/values-el/strings.xml
+++ b/app/ui/legacy/src/main/res/values-el/strings.xml
@@ -329,9 +329,6 @@
   Διακρίβωση στοιχείων\u2026
   Μετάκληση πληροφοριών λογαριασμού\u2026
   Ακύρωση\u2026
-  Σχεδόν έτοιμο!
-  Ονομασία λογαριασμού (Προαιρετικό):
-  Όνομα αποστολέα (προβάλλεται στα εξερχόμενα μηνύματα):
   Τύπος λογαριασμού
   Τι λογαριασμός είναι αυτός;
   POP3
diff --git a/app/ui/legacy/src/main/res/values-eo/strings.xml b/app/ui/legacy/src/main/res/values-eo/strings.xml
index b6c8cb7a64..9fade1c8f4 100644
--- a/app/ui/legacy/src/main/res/values-eo/strings.xml
+++ b/app/ui/legacy/src/main/res/values-eo/strings.xml
@@ -301,9 +301,6 @@ Bonvolu raporti erarojn, kontribui novajn eblojn kaj peti pri novaj funkcioj per
   Aŭtentigado\u2026
   Ŝargado de agordoj de konto\u2026
   Nuligado\u2026
-  Preskaŭ farite!
-  Nomi tiun ĉi konton (malnepre):
-  Entajpu vian nomon (montrata en eliraj mesaĝoj):
   Konta tipo
   De iu tipo tiu ĉi konto estas?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-es/strings.xml b/app/ui/legacy/src/main/res/values-es/strings.xml
index fc404f6c34..c07f73da19 100644
--- a/app/ui/legacy/src/main/res/values-es/strings.xml
+++ b/app/ui/legacy/src/main/res/values-es/strings.xml
@@ -331,9 +331,6 @@ Puedes informar de fallos, contribuir con su desarrollo y hacer preguntas en Autentificando\u2026
   Obteniendo configuración de la cuenta\u2026
   Cancelando\u2026
-  ¡Ya casi estás!
-  Elige un nombre para esta cuenta (opcional):
-  Pon tu nombre (aparecerá en los mensajes que envíes):
   Tipo de cuenta
   ¿Qué tipo de cuenta es?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-et/strings.xml b/app/ui/legacy/src/main/res/values-et/strings.xml
index 71907e2449..abd5f91d81 100644
--- a/app/ui/legacy/src/main/res/values-et/strings.xml
+++ b/app/ui/legacy/src/main/res/values-et/strings.xml
@@ -332,9 +332,6 @@ Veateated saad saata, kaastööd teha ning küsida teavet järgmisel lehel:
   Autentimine\u2026
   Toob konto sätteid\u2026
   Tühistamine\u2026
-  Oled peaaegu valmis!
-  Anna sellele kontole nimi (valikuline):
-  Trüki oma nimi (näidatakse väljuvates kirjades):
   Konto liik
   Mis tüüpi konto see on?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-eu/strings.xml b/app/ui/legacy/src/main/res/values-eu/strings.xml
index 233547149e..90976b961c 100644
--- a/app/ui/legacy/src/main/res/values-eu/strings.xml
+++ b/app/ui/legacy/src/main/res/values-eu/strings.xml
@@ -322,9 +322,6 @@ Mesedez akatsen berri emateko, ezaugarri berriak gehitzeko eta galderak egiteko
   Autentifikatzen\u2026
   Kontuaren ezarpenak eskuratzen\u2026
   Bertan behera uzten\u2026
-  Ia amaitu duzu!
-  Eman izen bat kontu honi (aukerakoa):
-  Idatzi zure izena (irteerako mezuetan bistaratuko da):
   Kontu mota
   Zein kontu mota da hau?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-fa/strings.xml b/app/ui/legacy/src/main/res/values-fa/strings.xml
index 02254430a2..6e2c8aba3f 100644
--- a/app/ui/legacy/src/main/res/values-fa/strings.xml
+++ b/app/ui/legacy/src/main/res/values-fa/strings.xml
@@ -330,9 +330,6 @@
   احراز هویت\u2026
   واکشی تنظیمات حساب کاربری\u2026
   لغوکردن\u2026
-  تقریباً تمام شد!
-  نامی برای این حساب انتخاب کنید (اختیاری):
-  نام خود را بنویسید (در پیام‌های ارسالی نمایش داده می‌شود):
   نوع حساب کاربری
   نوع این حساب کاربری چیست؟
   POP3
diff --git a/app/ui/legacy/src/main/res/values-fi/strings.xml b/app/ui/legacy/src/main/res/values-fi/strings.xml
index a883136289..69da5ea1d5 100644
--- a/app/ui/legacy/src/main/res/values-fi/strings.xml
+++ b/app/ui/legacy/src/main/res/values-fi/strings.xml
@@ -330,9 +330,6 @@ Ilmoita virheistä, ota osaa sovelluskehitykseen ja esitä kysymyksiä osoittees
   Varmistetaan\u2026
   Haetaan tilin asetuksia\u2026
   Peruutetaan\u2026
-  Melkein valmista!
-  Anna tilin nimi (ei pakollinen):
-  Anna nimesi (näkyy lähtevissä viesteissä):
   Tilin tyyppi
   Mikä tämän tilin tyyppi on?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-fr/strings.xml b/app/ui/legacy/src/main/res/values-fr/strings.xml
index 04ddb9e9ba..b545d374ef 100644
--- a/app/ui/legacy/src/main/res/values-fr/strings.xml
+++ b/app/ui/legacy/src/main/res/values-fr/strings.xml
@@ -334,9 +334,6 @@ Rapportez les bogues, recommandez de nouvelles fonctions et posez vos questions
   Authentification\u2026
   Récupération des paramètres du compte\u2026
   Annulation\u2026
-  Vous avez presque terminé !
-  Donner un nom à ce compte (facultatif) :
-  Saisissez votre nom (s’affiche dans les courriels sortants) :
   Type de compte
   Quel type de compte est-ce ?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-fy/strings.xml b/app/ui/legacy/src/main/res/values-fy/strings.xml
index e79df19ee3..6b66c3e984 100644
--- a/app/ui/legacy/src/main/res/values-fy/strings.xml
+++ b/app/ui/legacy/src/main/res/values-fy/strings.xml
@@ -326,9 +326,6 @@ Graach flaterrapporten stjoere, bydragen foar nije funksjes en fragen stelle op
   Autentikaasje\u2026
   Accountynstellingen ophelje\u2026
   Annulearje\u2026
-  Hast klear!
-  Jou dit account in namme (opsjoneel):
-  Typ jo namme (sichtber by útgeande berjochten):
   Accounttype
   Hokker type account is dit?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-gd/strings.xml b/app/ui/legacy/src/main/res/values-gd/strings.xml
index 94af999374..c8860fd7e6 100644
--- a/app/ui/legacy/src/main/res/values-gd/strings.xml
+++ b/app/ui/legacy/src/main/res/values-gd/strings.xml
@@ -266,9 +266,6 @@
   ’Ga dhearbhadh…
   A’ faighinn roghainnean a’ chunntais…
   A’ sgur dheth…
-  Cha mhòr deiseil!
-  Thoir ainm air a’ chunntas seo
-  Cuir a-steach d’ ainm (chithear seo ann an teachdaireachdan a thèid a-mach):
   Seòrsa a’ chunntais
   Dè seòrsa cunntas a tha seo\?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-gl/strings.xml b/app/ui/legacy/src/main/res/values-gl/strings.xml
index 63577928a5..0e4b3cc03f 100644
--- a/app/ui/legacy/src/main/res/values-gl/strings.xml
+++ b/app/ui/legacy/src/main/res/values-gl/strings.xml
@@ -307,9 +307,6 @@ Por favor envíen informes de fallos, contribúa con novas características e co
   Autentificando\u2026
   Obtendo Configuración da conta\u2026
   Cancelando\u2026
-  Feito!
-  Dalle un nome a esta conta (opcional):
-  Introduce o teu nome (visualizarase na mensaxe de saída):
   Tipo de conta
   Qué tipo de conta é?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-hr/strings.xml b/app/ui/legacy/src/main/res/values-hr/strings.xml
index b2f42a8cf8..6ddd9ebd1e 100644
--- a/app/ui/legacy/src/main/res/values-hr/strings.xml
+++ b/app/ui/legacy/src/main/res/values-hr/strings.xml
@@ -253,9 +253,6 @@
   Identifikacija\u2026
   Dohvaćam postavke računa\u2026
   Otkazujem\u2026
-  Uskoro ste gotovi!
-  Dajte naziv ovom računu (opcionalno):
-  Unesite vaše ime (prikazuje se na odlaznim porukama):
   Vrsta računa
   Kakav je to račun?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-hu/strings.xml b/app/ui/legacy/src/main/res/values-hu/strings.xml
index 367e5a2ce2..d085bfa208 100644
--- a/app/ui/legacy/src/main/res/values-hu/strings.xml
+++ b/app/ui/legacy/src/main/res/values-hu/strings.xml
@@ -329,9 +329,6 @@ Hibajelentések beküldésével közreműködhet az új funkciókban, és kérd
   Hitelesítés\u2026
   Fiókbeállítások beolvasása\u2026
   Megszakítás\u2026
-  Már majdnem kész.
-  Fiók elnevezése (nem kötelező):
-  Név megadása (kimenő üzeneteknél jelenik meg):
   Fióktípus
   Milyen fajta fiók ez?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-in/strings.xml b/app/ui/legacy/src/main/res/values-in/strings.xml
index 187285d357..bda8ff0a1a 100644
--- a/app/ui/legacy/src/main/res/values-in/strings.xml
+++ b/app/ui/legacy/src/main/res/values-in/strings.xml
@@ -291,9 +291,6 @@ Kirimkan laporan bug, kontribusikan fitur baru dan ajukan pertanyaan di
   Otentikasi\u2026
   Mengambil pengaturan akun\u2026
   Membatalkan\u2026
-  Anda hampir selesai!
-  Berikan akun ini sebuah nama (opsional):
-  Ketik nama Anda (ditampilkan pada pesan keluar):
   Tipe akun
   Akun apa ini?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-is/strings.xml b/app/ui/legacy/src/main/res/values-is/strings.xml
index 5e3432223b..d21af11268 100644
--- a/app/ui/legacy/src/main/res/values-is/strings.xml
+++ b/app/ui/legacy/src/main/res/values-is/strings.xml
@@ -331,9 +331,6 @@ Sendu inn villuskýrslur, leggðu fram nýja eiginleika og spurðu spurninga á
   Auðkenni\u2026
   Næ í stillingar aðgangs\u2026
   Hætti við\u2026
-  Þetta er næstum búið!
-  Gefðu þessum aðgangi nafn (valkvætt):
-  Skrifaðu nafnið þitt (er birt á útsendum skilaboðum):
   Gerð aðgangs
   Hvers konar aðgangur er þetta?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-it/strings.xml b/app/ui/legacy/src/main/res/values-it/strings.xml
index c68e8f5106..72c914d917 100644
--- a/app/ui/legacy/src/main/res/values-it/strings.xml
+++ b/app/ui/legacy/src/main/res/values-it/strings.xml
@@ -334,9 +334,6 @@ Invia segnalazioni di bug, contribuisci con nuove funzionalità e poni domande s
   Autenticazione\u2026
   Recupero delle impostazioni dell\'account in corso\u2026
   Annullamento in corso\u2026
-  Hai quasi fatto!
-  Assegna un nome all\'account (facoltativo):
-  Scrivi il tuo nome (visualizzato nei messaggi in uscita):
   Tipo di account
   Che tipo di account è questo?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-iw/strings.xml b/app/ui/legacy/src/main/res/values-iw/strings.xml
index 7b0d79cd0a..85538c861f 100644
--- a/app/ui/legacy/src/main/res/values-iw/strings.xml
+++ b/app/ui/legacy/src/main/res/values-iw/strings.xml
@@ -254,9 +254,6 @@
   מאמת …
   מייבא הגדרות החשבון …
   מבטל…
-  כמעט מוכן!
-  תן שם לחשבון זה (לא חובה):
-  הקלד את שמך (מוצג בהודעות יוצאות):
   סוג חשבון
   איזה סוג חשבון זה?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-ja/strings.xml b/app/ui/legacy/src/main/res/values-ja/strings.xml
index c98d4c804a..6f63dbc061 100644
--- a/app/ui/legacy/src/main/res/values-ja/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ja/strings.xml
@@ -328,9 +328,6 @@ K-9 は大多数のメールクライアントと同様に、ほとんどのフ
   認証中\u2026
   アカウント設定を取得中\u2026
   中断\u2026
-  電子メールセットアップ
-  アカウントの名前を付けます (オプション):
-  名前を入力します (送信メールの表示名):
   メールアカウント種類の選択
   受信メールサーバの種類を選択して下さい
   POP3 サーバ
diff --git a/app/ui/legacy/src/main/res/values-ko/strings.xml b/app/ui/legacy/src/main/res/values-ko/strings.xml
index 94c991d0e8..6b2bf47ade 100644
--- a/app/ui/legacy/src/main/res/values-ko/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ko/strings.xml
@@ -268,9 +268,6 @@
   인증 중\u2026
   계정 설정 가져 오기\u2026
   취소 중\u2026
-  설정이 거의 완료되었습니다!
-  이 계정의 이름을 입력 (옵션):
-  이름 입력 (보내는 메시지에 표시 될 이름):
   계정 종류
   계정 유형을 선택하시오.
   POP3
diff --git a/app/ui/legacy/src/main/res/values-lt/strings.xml b/app/ui/legacy/src/main/res/values-lt/strings.xml
index 27857cfcb7..bb93a405b5 100644
--- a/app/ui/legacy/src/main/res/values-lt/strings.xml
+++ b/app/ui/legacy/src/main/res/values-lt/strings.xml
@@ -327,9 +327,6 @@ Pateikite pranešimus apie klaidas, prisidėkite prie naujų funkcijų kūrimo i
   Patvirtinama tapatybė\u2026
   Gaunami paskyros nustatymai\u2026
   Atšaukiama\u2026
-  Beveik baigėte!
-  Pavadinkite šią paskyrą (nebūtina):
-  Įrašykite savo vardą (rodoma siunčiamuose pranešimuose):
   Paskyros tipas
   Kokios rūšies ši paskyra?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-lv/strings.xml b/app/ui/legacy/src/main/res/values-lv/strings.xml
index 8a7856f351..d273e39ad0 100644
--- a/app/ui/legacy/src/main/res/values-lv/strings.xml
+++ b/app/ui/legacy/src/main/res/values-lv/strings.xml
@@ -333,9 +333,6 @@ pat %d vairāk
   Pārbauda identifikāciju\u2026
   Saņem konta iestatījumus\u2026
   Atceļ\u2026
-  Gandrīz viss pabeigts!
-  Nosaukt kontu (nav obligāti):
-  Ierakstiet savu vārdu (attēlošanai izejošajās vēstulēs):
   Konta veids
   Kāda veida konts tas ir?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-ml/strings.xml b/app/ui/legacy/src/main/res/values-ml/strings.xml
index efcdc21103..bab7c9c7f7 100644
--- a/app/ui/legacy/src/main/res/values-ml/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ml/strings.xml
@@ -308,9 +308,6 @@
   പ്രാമാണീകരിക്കുന്നു\u2026
   അക്കൗണ്ട് ക്രമീകരണങ്ങൾ ലഭ്യമാക്കുന്നു\u2026
   റദ്ദാക്കുന്നു\u2026
-  നിങ്ങൾ ഏകദേശം പൂർത്തിയാക്കി!
-  ഈ അക്കൗണ്ടിന് ഒരു പേര് നൽകുക (ഐച്ഛികം):
-  നിങ്ങളുടെ പേര് ടൈപ്പുചെയ്യുക (ഔട്ട്‌ഗോയിംഗ് സന്ദേശങ്ങളിൽ പ്രദർശിപ്പിക്കുന്നു):
   അക്കൗണ്ട് തരം
   ഇത് ഏത് തരത്തിലുള്ള അക്കൗണ്ടാണ്?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-nb/strings.xml b/app/ui/legacy/src/main/res/values-nb/strings.xml
index 27757c32ed..fb61266d8b 100644
--- a/app/ui/legacy/src/main/res/values-nb/strings.xml
+++ b/app/ui/legacy/src/main/res/values-nb/strings.xml
@@ -289,9 +289,6 @@ til %d flere
   Autentiserer\u2026
   Henter kontoinnstillinger\u2026
   Avbryter\u2026
-  Du er nesten ferdig!
-  Gi denne kontoen et navn (valgfritt):
-  Skriv ditt navn (vises i utgående meldinger):
   Kontotype
   Hvilken type konto er dette?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-nl/strings.xml b/app/ui/legacy/src/main/res/values-nl/strings.xml
index ba5cf61fc2..ae04630125 100644
--- a/app/ui/legacy/src/main/res/values-nl/strings.xml
+++ b/app/ui/legacy/src/main/res/values-nl/strings.xml
@@ -326,9 +326,6 @@ Graag foutrapporten sturen, bijdragen voor nieuwe functies en vragen stellen op
   Authenticatie\u2026
   Accountinstellingen worden opgehaald\u2026
   Annuleren\u2026
-  Bijna klaar!
-  Geef dit account een naam (optioneel):
-  Typ je naam (zichtbaar bij uitgaande berichten):
   Accounttype
   Welk type account is dit?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-pl/strings.xml b/app/ui/legacy/src/main/res/values-pl/strings.xml
index f1abf92317..4bcb6e21c9 100644
--- a/app/ui/legacy/src/main/res/values-pl/strings.xml
+++ b/app/ui/legacy/src/main/res/values-pl/strings.xml
@@ -335,9 +335,6 @@ Wysłane z urządzenia Android za pomocą K-9 Mail. Proszę wybaczyć moją zwi
   Uwierzytelnianie…
   Pobieranie ustawień konta…
   Anulowanie…
-  Prawie gotowe!
-  Wpisz nazwę (opcjonalną) tego konta:
-  Twoje imię i nazwisko (pojawi się w wysyłanych wiadomościach):
   Rodzaj konta
   Jakiego typu serwer obsługuje to konto?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml
index 17710d20b8..542e6552a7 100644
--- a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml
+++ b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml
@@ -332,9 +332,6 @@ Por favor encaminhe relatórios de bugs, contribua com novos recursos e tire dú
   Autenticando\u2026
   Buscando as configurações da conta\u2026
   Cancelando\u2026
-  Quase terminado!
-  Dê um nome a esta conta (opcional):
-  Digite seu nome (será exibido nas mensagens enviadas):
   Tipo de conta
   Esta conta é de que tipo?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml
index c44788cc7a..557226d06b 100644
--- a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml
+++ b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml
@@ -334,9 +334,6 @@ Por favor envie relatórios de falhas, contribua com novas funcionalidades e col
   A autenticar\u2026
   A obter configurações da conta\u2026
   A cancelar\u2026
-  Está quase terminado!
-  Dê um nome a esta conta (opcional):
-  Introduza o seu nome (é exibido nas mensagens enviadas):
   Tipo de conta
   Que tipo de conta é esta?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-ro/strings.xml b/app/ui/legacy/src/main/res/values-ro/strings.xml
index 7587d8de7c..3a222f144f 100644
--- a/app/ui/legacy/src/main/res/values-ro/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ro/strings.xml
@@ -329,9 +329,6 @@ cel mult încă %d
   Autentifică\u2026
   Preluarea setărilor contului\u2026
   Se întrerupe\u2026
-  Ești aproape gata!
-  Dă acestui cont un nume (opțional):
-  Tastează numele tău (cum va fi afișat pe mesajele trimise):
   Tipul contului
   Ce fel de cont este acesta?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-ru/strings.xml b/app/ui/legacy/src/main/res/values-ru/strings.xml
index 83e77a7f5c..580e828fd3 100644
--- a/app/ui/legacy/src/main/res/values-ru/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ru/strings.xml
@@ -334,9 +334,6 @@ K-9 Mail — почтовик для Android.
   Аутентификация\u2026
   Получение настроек\u2026
   Отмена\u2026
-  Всё почти готово!
-  Название учётной записи (необязательно):
-  Ваше имя (видно адресату в сообщениях):
   Тип учётной записи
   Доступные протоколы
   POP3
diff --git a/app/ui/legacy/src/main/res/values-sk/strings.xml b/app/ui/legacy/src/main/res/values-sk/strings.xml
index 0ef6fb0bcf..4e6fcde02a 100644
--- a/app/ui/legacy/src/main/res/values-sk/strings.xml
+++ b/app/ui/legacy/src/main/res/values-sk/strings.xml
@@ -294,9 +294,6 @@ Prosím, nahlasujte prípadné chyby, prispievajte novými funkciami a pýtajte
   Overovanie\u2026
   Načítavanie nastavení účtu\u2026
   Rušenie\u2026
-  Takmer hotovo!
-  Pomenovať tento účet (voliteľné):
-  Zadajte vaše meno (zobrazí sa v odchádzajúcich správach):
   Typ účtu
   Typ účtu
   POP3
diff --git a/app/ui/legacy/src/main/res/values-sl/strings.xml b/app/ui/legacy/src/main/res/values-sl/strings.xml
index 1e3c06eeb5..a14496444f 100644
--- a/app/ui/legacy/src/main/res/values-sl/strings.xml
+++ b/app/ui/legacy/src/main/res/values-sl/strings.xml
@@ -331,9 +331,6 @@ dodatnih %d sporočil
   Overjanje \u2026
   Pridobivanje nastavitev računa \u2026
   Poteka preklic \u2026
-  Račun je že skoraj pripravljen!
-  Prikazano ime računa (izbirno):
-  Ime pošiljatelja (prikazano v vseh odhodnih sporočilih):
   Vrsta računa
   Kakšne vrste je račun?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-sq/strings.xml b/app/ui/legacy/src/main/res/values-sq/strings.xml
index 9fe3f394c9..85b264e35b 100644
--- a/app/ui/legacy/src/main/res/values-sq/strings.xml
+++ b/app/ui/legacy/src/main/res/values-sq/strings.xml
@@ -331,9 +331,6 @@ Ju lutemi, parashtrim njoftimesh për të meta, kontribute për veçori të reaj
   Po kryhet mirëfilltësimi\u2026
   Po sillen rregullime llogarie\u2026
   Po anulohet\u2026
-  Thuajse mbaruat!
-  Jepini një emër kësaj llogarie (në daçi):
-  Shtypni emrin tuaj (shfaqet në mesazhet e dërguara):
   Lloj llogarie
   Ç\’lloj llogarie është kjo?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-sr/strings.xml b/app/ui/legacy/src/main/res/values-sr/strings.xml
index cc7dc4e64c..621e7fc0e5 100644
--- a/app/ui/legacy/src/main/res/values-sr/strings.xml
+++ b/app/ui/legacy/src/main/res/values-sr/strings.xml
@@ -292,9 +292,6 @@
   Аутентификујем\u2026
   Добављам поставке налога\u2026
   Одустајем\u2026
-  Скоро сте завршили!
-  Именујте овај налог (необавезно):
-  Унесите своје име (приказано на одлазним порукама):
   Тип налога
   Какав је ово налог?
   ПОП3
diff --git a/app/ui/legacy/src/main/res/values-sv/strings.xml b/app/ui/legacy/src/main/res/values-sv/strings.xml
index 3459cc9457..b0d14cafa1 100644
--- a/app/ui/legacy/src/main/res/values-sv/strings.xml
+++ b/app/ui/legacy/src/main/res/values-sv/strings.xml
@@ -331,9 +331,6 @@ Skicka in felrapporter, bidra med nya funktioner och ställ frågor på
   Autentiserar\u2026
   Hämtar kontoinställningar\u2026
   Avbryter\u2026
-  Du är nästan klar!
-  Ge kontot ett namn (valfritt):
-  Ange ditt namn (visas på utgående e-post):
   Kontotyp
   Vilken typ av konto är detta?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-tr/strings.xml b/app/ui/legacy/src/main/res/values-tr/strings.xml
index 19e1dff3dd..a0543ff7a0 100644
--- a/app/ui/legacy/src/main/res/values-tr/strings.xml
+++ b/app/ui/legacy/src/main/res/values-tr/strings.xml
@@ -319,9 +319,6 @@ Microsoft Exchange ile konuşurken kimi tuhaflıklar yaşadığını lütfen akl
   Kimlik Doğrulaması\u2026
   Hesap ayarları alınıyor\u2026
   İptal ediliyor\u2026
-  Hemen hemen tamam!
-  Bu hesaba bir isim verin (isteğe bağlı):
-  İsminizi yazın (Giden mesajlarda görüntülenir):
   Hesap türü
   Bu ne tür bir hesaptır?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-uk/strings.xml b/app/ui/legacy/src/main/res/values-uk/strings.xml
index a73b166bfe..48ef66de60 100644
--- a/app/ui/legacy/src/main/res/values-uk/strings.xml
+++ b/app/ui/legacy/src/main/res/values-uk/strings.xml
@@ -336,9 +336,6 @@ K-9 Mail — це вільний клієнт електронної пошти
   Автентифікація\u2026
   Отримання налаштувань облікового запису\u2026
   Скасування\u2026
-  Майже готово!
-  Дайте ім’я цьому обліковому запису (необов’язково):
-  Введіть ваше ім’я (відображається у вихідних повідомленнях):
   Тип облікового запису
   Виберіть тип поштової скриньки
   POP3
diff --git a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml
index 21c3f02c71..fb0c5c03ed 100644
--- a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml
+++ b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml
@@ -329,9 +329,6 @@ K-9 Mail 是 Android 上一款功能强大的免费邮件客户端。
   正在验证用户\u2026
   正在获取账户设置\u2026
   正在取消\u2026
-  快要完成了!
-  为这个账户选择一个名称(可选项):
-  输入你的名字(将显示在发出的邮件中):
   账户类型
   这个账户是什么类型的?
   POP3
diff --git a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml
index c52fe84de2..406802a377 100644
--- a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml
+++ b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml
@@ -329,9 +329,6 @@ K-9 Mail 是 Android 上一款功能強大,免費的電子郵件用戶端。
   驗證…
   正在收取帳號設定…
   正在取消…
-  快要完成了!
-  為這個帳號選擇一個名稱(非必填):
-  輸入你的名字(將顯示在發出的郵件中):
   帳號類型
   這個帳號是什麼類型的?
   POP3
diff --git a/app/ui/legacy/src/main/res/values/strings.xml b/app/ui/legacy/src/main/res/values/strings.xml
index 097b1cead6..ae8074c97e 100644
--- a/app/ui/legacy/src/main/res/values/strings.xml
+++ b/app/ui/legacy/src/main/res/values/strings.xml
@@ -393,10 +393,6 @@ Please submit bug reports, contribute new features and ask questions at
     Fetching account settings\u2026
     Canceling\u2026
 
-    You\'re almost done!
-    Give this account a name (optional):
-    Type your name (displays on outgoing messages):
-
     Account type
     What kind of account is this?
     POP3
-- 
GitLab


From 89530e5b08f16c705d2a2e56c638694ade7fa461 Mon Sep 17 00:00:00 2001
From: cketti 
Date: Fri, 22 Sep 2023 18:17:59 +0200
Subject: [PATCH 65/94] Pass app name to `ImapServerSettingsValidator` for use
 with the IMAP ID command

---
 .../account/server/validation/ServerValidationModule.kt        | 3 ++-
 .../account/server/validation/ServerValidationModuleKtTest.kt  | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt
index 35f61cda13..8ebf966107 100644
--- a/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt
+++ b/feature/account/server/validation/src/main/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModule.kt
@@ -12,6 +12,7 @@ import com.fsck.k9.mail.store.imap.ImapServerSettingsValidator
 import com.fsck.k9.mail.store.pop3.Pop3ServerSettingsValidator
 import com.fsck.k9.mail.transport.smtp.SmtpServerSettingsValidator
 import org.koin.androidx.viewmodel.dsl.viewModel
+import org.koin.core.qualifier.named
 import org.koin.dsl.module
 
 val featureAccountServerValidationModule = module {
@@ -28,7 +29,7 @@ val featureAccountServerValidationModule = module {
             imapValidator = ImapServerSettingsValidator(
                 trustedSocketFactory = get(),
                 oAuth2TokenProviderFactory = get(),
-                clientIdAppName = "null", // TODO get real value
+                clientIdAppName = get(named("ClientIdAppName")),
             ),
             pop3Validator = Pop3ServerSettingsValidator(
                 trustedSocketFactory = get(),
diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt
index e6d2f7bdae..07258f240c 100644
--- a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt
+++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt
@@ -16,6 +16,7 @@ import org.junit.runner.RunWith
 import org.koin.android.ext.koin.androidContext
 import org.koin.core.annotation.KoinExperimentalAPI
 import org.koin.core.module.Module
+import org.koin.core.qualifier.named
 import org.koin.dsl.koinApplication
 import org.koin.dsl.module
 import org.koin.test.KoinTest
@@ -42,6 +43,7 @@ class ServerValidationModuleKtTest : KoinTest {
             }
         }
         single { Mockito.mock() }
+        single(named("ClientIdAppName")) { "App Name" }
     }
 
     @OptIn(KoinExperimentalAPI::class)
-- 
GitLab


From 8244470a9ec712a490a805541b3a46ae0148287a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Fri, 22 Sep 2023 18:27:04 +0200
Subject: [PATCH 66/94] Remove AccountSetupOptions

---
 app/k9mail/src/main/AndroidManifest.xml       |   5 -
 .../activity/setup/AccountSetupOptions.java   | 125 ------------------
 .../activity/setup/AccountSetupOutgoing.java  |   2 +-
 .../main/res/layout/account_setup_options.xml |  68 ----------
 .../legacy/src/main/res/values-ar/strings.xml |   2 -
 .../legacy/src/main/res/values-be/strings.xml |   2 -
 .../legacy/src/main/res/values-bg/strings.xml |   2 -
 .../legacy/src/main/res/values-br/strings.xml |   2 -
 .../legacy/src/main/res/values-ca/strings.xml |   2 -
 .../legacy/src/main/res/values-cs/strings.xml |   2 -
 .../legacy/src/main/res/values-cy/strings.xml |   2 -
 .../legacy/src/main/res/values-da/strings.xml |   2 -
 .../legacy/src/main/res/values-de/strings.xml |   2 -
 .../legacy/src/main/res/values-el/strings.xml |   2 -
 .../legacy/src/main/res/values-eo/strings.xml |   2 -
 .../legacy/src/main/res/values-es/strings.xml |   2 -
 .../legacy/src/main/res/values-et/strings.xml |   2 -
 .../legacy/src/main/res/values-eu/strings.xml |   2 -
 .../legacy/src/main/res/values-fa/strings.xml |   2 -
 .../legacy/src/main/res/values-fi/strings.xml |   2 -
 .../legacy/src/main/res/values-fr/strings.xml |   2 -
 .../legacy/src/main/res/values-fy/strings.xml |   2 -
 .../legacy/src/main/res/values-gd/strings.xml |   2 -
 .../legacy/src/main/res/values-gl/strings.xml |   2 -
 .../legacy/src/main/res/values-hr/strings.xml |   2 -
 .../legacy/src/main/res/values-hu/strings.xml |   2 -
 .../legacy/src/main/res/values-in/strings.xml |   2 -
 .../legacy/src/main/res/values-is/strings.xml |   2 -
 .../legacy/src/main/res/values-it/strings.xml |   2 -
 .../legacy/src/main/res/values-iw/strings.xml |   2 -
 .../legacy/src/main/res/values-ja/strings.xml |   2 -
 .../legacy/src/main/res/values-ko/strings.xml |   2 -
 .../legacy/src/main/res/values-lt/strings.xml |   2 -
 .../legacy/src/main/res/values-lv/strings.xml |   2 -
 .../legacy/src/main/res/values-ml/strings.xml |   2 -
 .../legacy/src/main/res/values-nb/strings.xml |   2 -
 .../legacy/src/main/res/values-nl/strings.xml |   2 -
 .../legacy/src/main/res/values-pl/strings.xml |   2 -
 .../src/main/res/values-pt-rBR/strings.xml    |   2 -
 .../src/main/res/values-pt-rPT/strings.xml    |   2 -
 .../legacy/src/main/res/values-ro/strings.xml |   2 -
 .../legacy/src/main/res/values-ru/strings.xml |   2 -
 .../legacy/src/main/res/values-sk/strings.xml |   2 -
 .../legacy/src/main/res/values-sl/strings.xml |   2 -
 .../legacy/src/main/res/values-sq/strings.xml |   2 -
 .../legacy/src/main/res/values-sr/strings.xml |   2 -
 .../legacy/src/main/res/values-sv/strings.xml |   2 -
 .../legacy/src/main/res/values-tr/strings.xml |   2 -
 .../legacy/src/main/res/values-uk/strings.xml |   2 -
 .../src/main/res/values-zh-rCN/strings.xml    |   2 -
 .../src/main/res/values-zh-rTW/strings.xml    |   2 -
 app/ui/legacy/src/main/res/values/strings.xml |   2 -
 52 files changed, 1 insertion(+), 295 deletions(-)
 delete mode 100644 app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupOptions.java
 delete mode 100644 app/ui/legacy/src/main/res/layout/account_setup_options.xml

diff --git a/app/k9mail/src/main/AndroidManifest.xml b/app/k9mail/src/main/AndroidManifest.xml
index 69b476f9a7..cad908a1b4 100644
--- a/app/k9mail/src/main/AndroidManifest.xml
+++ b/app/k9mail/src/main/AndroidManifest.xml
@@ -95,11 +95,6 @@
             android:configChanges="locale"
             android:label="@string/account_setup_outgoing_title"/>
 
-        
-
          checkFrequenciesAdapter = new ArrayAdapter<>(this,
-                android.R.layout.simple_spinner_item, checkFrequencies);
-        checkFrequenciesAdapter
-        .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-        mCheckFrequencyView.setAdapter(checkFrequenciesAdapter);
-
-        SpinnerOption displayCounts[] = {
-            new SpinnerOption(10, getString(R.string.account_setup_options_mail_display_count_10)),
-            new SpinnerOption(25, getString(R.string.account_setup_options_mail_display_count_25)),
-            new SpinnerOption(50, getString(R.string.account_setup_options_mail_display_count_50)),
-            new SpinnerOption(100, getString(R.string.account_setup_options_mail_display_count_100)),
-            new SpinnerOption(250, getString(R.string.account_setup_options_mail_display_count_250)),
-            new SpinnerOption(500, getString(R.string.account_setup_options_mail_display_count_500)),
-            new SpinnerOption(1000, getString(R.string.account_setup_options_mail_display_count_1000)),
-        };
-
-        ArrayAdapter displayCountsAdapter = new ArrayAdapter<>(this,
-                android.R.layout.simple_spinner_item, displayCounts);
-        displayCountsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-        mDisplayCountView.setAdapter(displayCountsAdapter);
-
-        String accountUuid = getIntent().getStringExtra(EXTRA_ACCOUNT);
-        mAccount = Preferences.getPreferences().getAccount(accountUuid);
-
-        mNotifyView.setChecked(mAccount.isNotifyNewMail());
-        SpinnerOption.setSpinnerOptionValue(mCheckFrequencyView, mAccount
-                                            .getAutomaticCheckIntervalMinutes());
-        SpinnerOption.setSpinnerOptionValue(mDisplayCountView, mAccount
-                                            .getDisplayCount());
-    }
-
-    private void onDone() {
-        mAccount.setName(mAccount.getEmail());
-        mAccount.setNotifyNewMail(mNotifyView.isChecked());
-        mAccount.setAutomaticCheckIntervalMinutes((Integer)((SpinnerOption)mCheckFrequencyView
-                .getSelectedItem()).value);
-        mAccount.setDisplayCount((Integer)((SpinnerOption)mDisplayCountView
-                                           .getSelectedItem()).value);
-
-        mAccount.setFolderPushMode(Account.FolderMode.NONE);
-
-        Preferences.getPreferences().saveAccount(mAccount);
-        Core.setServicesEnabled(this);
-//        AccountSetupNames.actionSetNames(this, mAccount);
-    }
-
-    public void onClick(View v) {
-        if (v.getId() == R.id.next) {
-            onDone();
-        }
-    }
-}
diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupOutgoing.java b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupOutgoing.java
index d1c8d1732b..e7281a6e1c 100644
--- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupOutgoing.java
+++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/AccountSetupOutgoing.java
@@ -496,7 +496,7 @@ public class AccountSetupOutgoing extends K9Activity implements OnClickListener,
                 Preferences.getPreferences().saveAccount(mAccount);
                 finish();
             } else {
-                AccountSetupOptions.actionOptions(this, mAccount);
+//                AccountSetupOptions.actionOptions(this, mAccount);
             }
         }
     }
diff --git a/app/ui/legacy/src/main/res/layout/account_setup_options.xml b/app/ui/legacy/src/main/res/layout/account_setup_options.xml
deleted file mode 100644
index d15bc14c90..0000000000
--- a/app/ui/legacy/src/main/res/layout/account_setup_options.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-    
-
-    
-
-        
-
-            
-
-            
-
-            
-
-            
-
-            
-
-            
-        
-    
-
-    
-
diff --git a/app/ui/legacy/src/main/res/values-ar/strings.xml b/app/ui/legacy/src/main/res/values-ar/strings.xml
index 9facad5b5e..4e5c0ec37c 100644
--- a/app/ui/legacy/src/main/res/values-ar/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ar/strings.xml
@@ -388,7 +388,6 @@
   كلمة السِّر
   المصادقة
   إعداد غير صالح: %s
-  خيارات الحساب
   تردد استطلاع المجلد 
   أبدًا
   كل 15 دقيقة
@@ -408,7 +407,6 @@
   كل 36 دقيقة
   كل 48 دقيقة
   كل 60 دقيقة
-  نبهني عند وصول رسالة
   عدد الرسائل التي ستظهر
   10 رسائل
   25 رسالة
diff --git a/app/ui/legacy/src/main/res/values-be/strings.xml b/app/ui/legacy/src/main/res/values-be/strings.xml
index 926e686e8c..939a835515 100644
--- a/app/ui/legacy/src/main/res/values-be/strings.xml
+++ b/app/ui/legacy/src/main/res/values-be/strings.xml
@@ -385,7 +385,6 @@ K-9 Mail - шматфункцыянальны свабодны паштовы к
   Аўтэнтыфікацыя
   \"%1$s = %2$s\" непрыдатны для \"%3$s = %4$s\"
   Хібнае наладжванне: %s
-  Параметры акаўнта
   Частата апытання
   Ніколі
   Кожныя 15 хвілін
@@ -405,7 +404,6 @@ K-9 Mail - шматфункцыянальны свабодны паштовы к
   Кожныя 36 хвілін
   Кожныя 48 хвілін
   Кожныя 60 хвілін
-  Апавяшчаць пра новую пошту
   Колькасць лістоў для паказу
   10 лістоў
   25 лістоў
diff --git a/app/ui/legacy/src/main/res/values-bg/strings.xml b/app/ui/legacy/src/main/res/values-bg/strings.xml
index 24d707fd2a..ddcef0e607 100644
--- a/app/ui/legacy/src/main/res/values-bg/strings.xml
+++ b/app/ui/legacy/src/main/res/values-bg/strings.xml
@@ -347,7 +347,6 @@ K-9 Mail е мощен, безплатен имейл клиент за Андр
   Идентификация
   \"%1$s = %2$s\" не е валидно с \"%3$s = %4$s\"
   Невалидни настройки: %s
-  Настройки на профила
   Честота на проверка на папката
   Никога
   На всеки 15 минути
@@ -367,7 +366,6 @@ K-9 Mail е мощен, безплатен имейл клиент за Андр
   На всеки 36 минути
   На всеки 48 минути
   На всеки 60 минути
-  Уведоми ме когато пристигне поща
   Брой съобщения за показване
   10 съобщения
   25 съобщения
diff --git a/app/ui/legacy/src/main/res/values-br/strings.xml b/app/ui/legacy/src/main/res/values-br/strings.xml
index b60cc1a72a..6cb15c4ddd 100644
--- a/app/ui/legacy/src/main/res/values-br/strings.xml
+++ b/app/ui/legacy/src/main/res/values-br/strings.xml
@@ -328,7 +328,6 @@ Danevellit beugoù, kenlabourit war keweriusterioù nevez ha savit goulennoù wa
   Dilesa
   %1$s = %2$s\" n’eo ket talvoudek gant \"%3$s = %4$s
   Arventennoù didalvoudek: %s
-  Dibarzhioù ar gont
   Aliested kerc’hat ar posteloù
   Morse
   Bep 15 munutenn
@@ -348,7 +347,6 @@ Danevellit beugoù, kenlabourit war keweriusterioù nevez ha savit goulennoù wa
   Bep 36 munutenn
   Bep 48 munutenn
   Bep 60 munutenn
-  Ma rebuziñ pa zegouezh ar posteloù
   Niver a gemennadennoù da ziskouez
   10 kemennadenn
   25 kemennadenn
diff --git a/app/ui/legacy/src/main/res/values-ca/strings.xml b/app/ui/legacy/src/main/res/values-ca/strings.xml
index 4ccf034fdc..e1a02b2a85 100644
--- a/app/ui/legacy/src/main/res/values-ca/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ca/strings.xml
@@ -382,7 +382,6 @@ Si us plau, envieu informes d\'errors, contribuïu-hi amb noves millores i feu p
   Tipus d\'autenticació
   \"%1$s = %2$s\" no és vàlid amb \"%3$s = %4$s\"
   Configuració no vàlida: %s
-  Opcions del compte
   Freqüència de comprovació
   Mai
   Cada 15 minuts
@@ -402,7 +401,6 @@ Si us plau, envieu informes d\'errors, contribuïu-hi amb noves millores i feu p
   Cada 36 minuts
   Cada 48 minuts
   Cada 60 minuts
-  Avisa\'m quan arribi correu
   Nombre de missatges a mostrar
   10 missatges
   25 missatges
diff --git a/app/ui/legacy/src/main/res/values-cs/strings.xml b/app/ui/legacy/src/main/res/values-cs/strings.xml
index 56148e3102..e001863a96 100644
--- a/app/ui/legacy/src/main/res/values-cs/strings.xml
+++ b/app/ui/legacy/src/main/res/values-cs/strings.xml
@@ -386,7 +386,6 @@ Hlášení o chyb, úpravy pro nové funkce a dotazy zadávejte prostřednictví
   Typ ověření
   %1$s = %2$s“ není platný s „%3$s = %4$s
   Neplatné nastavení: %s
-  Možnosti účtu
   Frekvence dotazování složky
   Nikdy
   Každých 15 minut
@@ -406,7 +405,6 @@ Hlášení o chyb, úpravy pro nové funkce a dotazy zadávejte prostřednictví
   Každých 36 minut
   Každých 48 minut
   Každých 60 minut
-  Oznamuj mi příchod nové pošty
   Počet zobrazených zpráv
   10 zpráv
   25 zpráv
diff --git a/app/ui/legacy/src/main/res/values-cy/strings.xml b/app/ui/legacy/src/main/res/values-cy/strings.xml
index 78f231d9e8..d05442af57 100644
--- a/app/ui/legacy/src/main/res/values-cy/strings.xml
+++ b/app/ui/legacy/src/main/res/values-cy/strings.xml
@@ -372,7 +372,6 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
   Dilysiad
   Dyw \"%1$s = %2$s\" ddim yn dilys gyda \"%3$s = %4$s\"
   Gosodiad annilys: %s
-  Dewisiadau cyfrif
   Pa mor aml i wirio\'r ffolder
   Byth
   Pob 15 munud
@@ -392,7 +391,6 @@ Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwesti
   Pob 36 munud
   Pob 48 munud
   Pob 60 munud
-  Hysbysu pan ddaw neges newydd
   Nifer o negeseuon i\'w dangos
   10 neges
   25 neges
diff --git a/app/ui/legacy/src/main/res/values-da/strings.xml b/app/ui/legacy/src/main/res/values-da/strings.xml
index 0be62f47b6..3ba2aa0aa2 100644
--- a/app/ui/legacy/src/main/res/values-da/strings.xml
+++ b/app/ui/legacy/src/main/res/values-da/strings.xml
@@ -376,7 +376,6 @@ Rapporter venligst fejl, forslag til nye funktioner eller stil spørgsmål på:
   Autentifikationstype
   \"%1$s = %2$s\" er ikke gyldig med \"%3$s = %4$s\"
   Ugyldig opsætning: %s
-  Kontoindstillinger
   Frekvens for hentning af mail
   Aldrig
   Hver 15 minut
@@ -396,7 +395,6 @@ Rapporter venligst fejl, forslag til nye funktioner eller stil spørgsmål på:
   Hver 36 minut
   Hver 48 minut
   Hver 60 minut
-  Vis besked når mails ankommer
   Antal viste mails
   10 mails
   25 mails
diff --git a/app/ui/legacy/src/main/res/values-de/strings.xml b/app/ui/legacy/src/main/res/values-de/strings.xml
index e77b07a072..036cdc8dc5 100644
--- a/app/ui/legacy/src/main/res/values-de/strings.xml
+++ b/app/ui/legacy/src/main/res/values-de/strings.xml
@@ -381,7 +381,6 @@ Bitte sende Fehlerberichte, Ideen für neue Funktionen und stelle Fragen an
   Authentifizierungsmethode
   \"%1$s = %2$s\" ist nicht gültig mit \"%3$s = %4$s\"
   Ungültige Einstellung: %s
-  Kontooptionen
   E-Mail-Abfrage
   Nie (nur manuell)
   Alle 15 Minuten
@@ -401,7 +400,6 @@ Bitte sende Fehlerberichte, Ideen für neue Funktionen und stelle Fragen an
   Alle 36 Minuten
   Alle 48 Minuten
   Jede Stunde
-  Benachrichtigen, wenn Nachrichten eingehen
   Anzahl sichtbarer Nachrichten
   10 Nachrichten
   25 Nachrichten
diff --git a/app/ui/legacy/src/main/res/values-el/strings.xml b/app/ui/legacy/src/main/res/values-el/strings.xml
index 396b95a4a9..8af04d0ccb 100644
--- a/app/ui/legacy/src/main/res/values-el/strings.xml
+++ b/app/ui/legacy/src/main/res/values-el/strings.xml
@@ -379,7 +379,6 @@
   Πιστοποίηση
   Το «%1$s = %2$s» δεν είναι έγκυρο με «%3$s = %4$s»
   Άκυρη ρύθμιση: %s
-  Επιλογές λογαριασμού
   Συχνότητα ενημέρωσης φακέλων
   Ποτέ
   Κάθε 15 λεπτά
@@ -399,7 +398,6 @@
   Κάθε 36 λεπτά
   Κάθε 48 λεπτά
   Κάθε 60 λεπτά
-  Ειδοποίηση κατά την άφιξη μηνύματος
   Πλήθος μηνυμάτων που προβάλλονται
   10 μηνύματα
   25 μηνύματα
diff --git a/app/ui/legacy/src/main/res/values-eo/strings.xml b/app/ui/legacy/src/main/res/values-eo/strings.xml
index 9fade1c8f4..a6d24a1152 100644
--- a/app/ui/legacy/src/main/res/values-eo/strings.xml
+++ b/app/ui/legacy/src/main/res/values-eo/strings.xml
@@ -349,7 +349,6 @@ Bonvolu raporti erarojn, kontribui novajn eblojn kaj peti pri novaj funkcioj per
   Aŭtentigo
   \"%1$s = %2$s\" ne estas ĝusta kun \"%3$s = %4$s\"
   Erara agordaro: %s
-  Kontaj agordoj
   Ofteco de mesaĝuj-elŝuto
   Neniam
   Je ĉiuj 15 minutoj
@@ -369,7 +368,6 @@ Bonvolu raporti erarojn, kontribui novajn eblojn kaj peti pri novaj funkcioj per
   Je ĉiuj 36 minutoj
   Je ĉiuj 48 minutoj
   Je ĉiuj 60 minutoj
-  Sciigi kiam retletero alvenas
   Kiom da mesaĝoj montri
   10 mesaĝoj
   25 mesaĝoj
diff --git a/app/ui/legacy/src/main/res/values-es/strings.xml b/app/ui/legacy/src/main/res/values-es/strings.xml
index c07f73da19..0b02124379 100644
--- a/app/ui/legacy/src/main/res/values-es/strings.xml
+++ b/app/ui/legacy/src/main/res/values-es/strings.xml
@@ -382,7 +382,6 @@ Puedes informar de fallos, contribuir con su desarrollo y hacer preguntas en Tipo de autentificación
   La opción «%1$s = %2$s» no es compatible con «%3$s = %4$s»
   Configuración incorrecta: %s
-  Opciones de cuenta
   Frecuencia de comprobación de correo nuevo
   Nunca
   Cada 15 minutos
@@ -402,7 +401,6 @@ Puedes informar de fallos, contribuir con su desarrollo y hacer preguntas en Cada 36 minutos
   Cada 48 minutos
   Cada 60 minutos
-  Avisarme cuando lleguen nuevos mensajes
   Número de mensajes a mostrar
   10 mensajes
   25 mensajes
diff --git a/app/ui/legacy/src/main/res/values-et/strings.xml b/app/ui/legacy/src/main/res/values-et/strings.xml
index abd5f91d81..2c616af7d8 100644
--- a/app/ui/legacy/src/main/res/values-et/strings.xml
+++ b/app/ui/legacy/src/main/res/values-et/strings.xml
@@ -383,7 +383,6 @@ Veateated saad saata, kaastööd teha ning küsida teavet järgmisel lehel:
   Autentimine
   \"%1$s = %2$s\" ei valideeru seadega \"%3$s = %4$s\"
   Vigased sätted: %s
-  Konto valikud
   Kausta pollimise sagedus
   Mitte kunagi
   Iga 15 minuti tagant
@@ -403,7 +402,6 @@ Veateated saad saata, kaastööd teha ning küsida teavet järgmisel lehel:
   Iga 36 minuti tagant
   Iga 48 minuti tagant
   Iga 60 minuti tagant
-  Teavita uue e-kirja saabumisest
   Kuvatavate kirjade arv
   10 kirja
   25 kirja
diff --git a/app/ui/legacy/src/main/res/values-eu/strings.xml b/app/ui/legacy/src/main/res/values-eu/strings.xml
index 90976b961c..12a3028713 100644
--- a/app/ui/legacy/src/main/res/values-eu/strings.xml
+++ b/app/ui/legacy/src/main/res/values-eu/strings.xml
@@ -372,7 +372,6 @@ Mesedez akatsen berri emateko, ezaugarri berriak gehitzeko eta galderak egiteko
   Autentifikazioa
   \"%1$s = %2$s\" ez da baliozkoa \"%3$s = %4$s\"-(r)ekin
   Konfigurazio baliogabea: %s
-  Kontu aukerak
   Karpeta atzitzeko maiztasuna
   Inoiz ez
   15 minutuero
@@ -392,7 +391,6 @@ Mesedez akatsen berri emateko, ezaugarri berriak gehitzeko eta galderak egiteko
   36 minutuero
   48 minutuero
   60 minutuero
-  Jakinarazi niri posta iristean
   Bistaratuko den mezu kopurua
   10 mezu
   25 mezu
diff --git a/app/ui/legacy/src/main/res/values-fa/strings.xml b/app/ui/legacy/src/main/res/values-fa/strings.xml
index 6e2c8aba3f..bad5f0e6dc 100644
--- a/app/ui/legacy/src/main/res/values-fa/strings.xml
+++ b/app/ui/legacy/src/main/res/values-fa/strings.xml
@@ -381,7 +381,6 @@
   احراز هویت
   «%1$s = %2$s» با «%3$s = %4$s» معتبر نیست
   پیکربندی نادرست: %s
-  گزینه‌های حساب کاربری
   تکرار سرکشی به پوشه
   هرگز
   هر ۱۵ دقیقه
@@ -401,7 +400,6 @@
   هر ۳۶ دقیقه
   هر ۴۸ دقیقه
   هر ۶۰ دقیقه
-  هر زمان رایانامه رسید به من خبر بده
   تعداد پیام‌ها برای نمایش
   ۱۰ پیام
   ۲۵ پیام
diff --git a/app/ui/legacy/src/main/res/values-fi/strings.xml b/app/ui/legacy/src/main/res/values-fi/strings.xml
index 69da5ea1d5..2818bf24d2 100644
--- a/app/ui/legacy/src/main/res/values-fi/strings.xml
+++ b/app/ui/legacy/src/main/res/values-fi/strings.xml
@@ -381,7 +381,6 @@ Ilmoita virheistä, ota osaa sovelluskehitykseen ja esitä kysymyksiä osoittees
   Todennustapa
   \"%1$s = %2$s\" ei ole kelvollinen asetuksen \"%3$s = %4$s\" kanssa
   Virheellinen asetus: %s
-  Tilin asetukset
   Viestien tarkistus
   Ei koskaan
   Joka 15 minuutti
@@ -401,7 +400,6 @@ Ilmoita virheistä, ota osaa sovelluskehitykseen ja esitä kysymyksiä osoittees
   Joka 36 minuutti
   Joka 48 minuutti
   Joka 60 minuutti
-  Ilmoitus postin saapumisesta
   Näytettävien viestien lukumäärä
   10 kansiota
   25 kansiota
diff --git a/app/ui/legacy/src/main/res/values-fr/strings.xml b/app/ui/legacy/src/main/res/values-fr/strings.xml
index b545d374ef..f5ab6c8a51 100644
--- a/app/ui/legacy/src/main/res/values-fr/strings.xml
+++ b/app/ui/legacy/src/main/res/values-fr/strings.xml
@@ -385,7 +385,6 @@ Rapportez les bogues, recommandez de nouvelles fonctions et posez vos questions
   Authentification
   « %1$s = %2$s » n’est pas valide avec « %3$s = %4$s »
   Paramétrage invalide : %s
-  Options du compte
   Fréquence de scrutation des dossiers
   Jamais
   Toutes les 15 minutes
@@ -405,7 +404,6 @@ Rapportez les bogues, recommandez de nouvelles fonctions et posez vos questions
   Toutes les 36 minutes
   Toutes les 48 minutes
   Toutes les 60 minutes
-  M’avertir lors de l’arrivée de courriels
   Nombre de courriels à afficher
   10 courriels
   25 courriels
diff --git a/app/ui/legacy/src/main/res/values-fy/strings.xml b/app/ui/legacy/src/main/res/values-fy/strings.xml
index 6b66c3e984..f6909e781d 100644
--- a/app/ui/legacy/src/main/res/values-fy/strings.xml
+++ b/app/ui/legacy/src/main/res/values-fy/strings.xml
@@ -377,7 +377,6 @@ Graach flaterrapporten stjoere, bydragen foar nije funksjes en fragen stelle op
   Autentikaasjetype
   %1$s = %2$s’ is net jildich mei ‘%3$s = %4$s
   Unjildige ynstellingen: %s
-  Accountopsjes
   Frekwinsje mapkontrôle
   Nea
   Elke 15 minuten
@@ -397,7 +396,6 @@ Graach flaterrapporten stjoere, bydragen foar nije funksjes en fragen stelle op
   Elke 36 minuten
   Elke 48 minuten
   Elke 60 minuten
-  Melding jaan by nij e-mailberjocht
   Tal berjochten om te toanen
   10 berjochten
   25 berjochten
diff --git a/app/ui/legacy/src/main/res/values-gd/strings.xml b/app/ui/legacy/src/main/res/values-gd/strings.xml
index c8860fd7e6..4694ffd1a4 100644
--- a/app/ui/legacy/src/main/res/values-gd/strings.xml
+++ b/app/ui/legacy/src/main/res/values-gd/strings.xml
@@ -314,7 +314,6 @@
   Dearbhadh
   Chan eil “%1$s = %2$s” dligheach mu choinneamh “%3$s = %4$s
   Suidheachadh mì-dhligheach: %s
-  Roghainnean a’ chunntais
   Dè cho tric ’s a dh’iarras sinn am post\?
   Chan ann idir
   Gach cairteal na h-uarach
@@ -334,7 +333,6 @@
   Gach 36 mionaid
   Gach 48 mionaid
   Gach uair a thìde
-  Thoir brath dhomh nuair a ruigeas post
   Co mheud teachdaireachd a thèid a shealltainn
   10 teachdaireachdan
   25 teachdaireachd
diff --git a/app/ui/legacy/src/main/res/values-gl/strings.xml b/app/ui/legacy/src/main/res/values-gl/strings.xml
index 0e4b3cc03f..fb388f6c67 100644
--- a/app/ui/legacy/src/main/res/values-gl/strings.xml
+++ b/app/ui/legacy/src/main/res/values-gl/strings.xml
@@ -355,7 +355,6 @@ Por favor envíen informes de fallos, contribúa con novas características e co
   Tipo de autentificación
   \"%1$s = %2$s\" non é válido con \"%3$s = %4$s\"
   Configuración inválida: %s
-  Opcións de conta
   Frecuencia de comprobación de correo
   Nunca
   Cada 15 minutos
@@ -375,7 +374,6 @@ Por favor envíen informes de fallos, contribúa con novas características e co
   Cada 36 minutos
   Cada 48 minutos
   Cada 60 minutos
-  Avisarme cando chegue correo
   Número de mensaxes a visualizar
   10 mensaxes
   25 mensaxes
diff --git a/app/ui/legacy/src/main/res/values-hr/strings.xml b/app/ui/legacy/src/main/res/values-hr/strings.xml
index 6ddd9ebd1e..bb51fee3ac 100644
--- a/app/ui/legacy/src/main/res/values-hr/strings.xml
+++ b/app/ui/legacy/src/main/res/values-hr/strings.xml
@@ -301,7 +301,6 @@
   Identifikacija
   \"%1$s = %2$s\" nije važeća sa \"%3$s = %4$s\"
   Nevažeće postavljanje: %s
-  Opcije računa
   Učestalost provjera mapa
   Nikad
   Svakih 15 minuta
@@ -321,7 +320,6 @@
   Svakih 36 minuta
   Svakih 48 minuta
   Svakih 60 minuta
-  Obavijesti me kod primitka pošte
   Broj poruka za prikaz
   10 poruka
   25 poruka
diff --git a/app/ui/legacy/src/main/res/values-hu/strings.xml b/app/ui/legacy/src/main/res/values-hu/strings.xml
index d085bfa208..a6b27f5785 100644
--- a/app/ui/legacy/src/main/res/values-hu/strings.xml
+++ b/app/ui/legacy/src/main/res/values-hu/strings.xml
@@ -380,7 +380,6 @@ Hibajelentések beküldésével közreműködhet az új funkciókban, és kérd
   Hitelesítés
   %1$s = %2$s” nem érvényes ezzel: „%3$s = %4$s
   Érvénytelen beállítás: %s
-  Fiók beállításai
   Mappa lekérdezésének gyakorisága
   Soha
   15 percenként
@@ -400,7 +399,6 @@ Hibajelentések beküldésével közreműködhet az új funkciókban, és kérd
   36 percenként
   48 percenként
   60 percenként
-  Értesítés, amikor levél érkezik
   Megjelenítendő üzenetek száma
   10 üzenet
   25 üzenet
diff --git a/app/ui/legacy/src/main/res/values-in/strings.xml b/app/ui/legacy/src/main/res/values-in/strings.xml
index bda8ff0a1a..1a28e41c96 100644
--- a/app/ui/legacy/src/main/res/values-in/strings.xml
+++ b/app/ui/legacy/src/main/res/values-in/strings.xml
@@ -339,7 +339,6 @@ Kirimkan laporan bug, kontribusikan fitur baru dan ajukan pertanyaan di
   Otentikasi
   \"%1$s = %2$s\" tidak valid dengan \"%3$s = %4$s\"
   Salah pengaturan: %s
-  Opsi akun
   Frekuensi penarikan folder
   Tidak pernah
   Setiap 15 menit
@@ -359,7 +358,6 @@ Kirimkan laporan bug, kontribusikan fitur baru dan ajukan pertanyaan di
   Setiap 36 Menit
   Setiap 48 Menit
   Setiap 60 Menit
-  Beritahu saya bila surat masuk
   Jumlah pesan yang akan ditampilkan
   10 pesan
   25 pesan
diff --git a/app/ui/legacy/src/main/res/values-is/strings.xml b/app/ui/legacy/src/main/res/values-is/strings.xml
index d21af11268..dd2c9eac7f 100644
--- a/app/ui/legacy/src/main/res/values-is/strings.xml
+++ b/app/ui/legacy/src/main/res/values-is/strings.xml
@@ -382,7 +382,6 @@ Sendu inn villuskýrslur, leggðu fram nýja eiginleika og spurðu spurninga á
   Auðkenning
   \"%1$s = %2$s\" er ekki gilt með \"%3$s = %4$s\"
   Ógild uppsetning: %s
-  Valkostir aðgangs
   Tíðni athugana á möppu
   Aldrei
   Á 15 mínútna fresti
@@ -402,7 +401,6 @@ Sendu inn villuskýrslur, leggðu fram nýja eiginleika og spurðu spurninga á
   Á 36 mínútna fresti
   Á 48 mínútna fresti
   Á 60 mínútna fresti
-  Láta mig vita þegar nýr póstur berst
   Fjöldi skilaboða sem á að birta
   10 skilaboð
   25 skilaboð
diff --git a/app/ui/legacy/src/main/res/values-it/strings.xml b/app/ui/legacy/src/main/res/values-it/strings.xml
index 72c914d917..a60ab4bae3 100644
--- a/app/ui/legacy/src/main/res/values-it/strings.xml
+++ b/app/ui/legacy/src/main/res/values-it/strings.xml
@@ -385,7 +385,6 @@ Invia segnalazioni di bug, contribuisci con nuove funzionalità e poni domande s
   Autenticazione
   \"%1$s = %2$s\" non è valido con \"%3$s = %4$s\"
   Configurazione non valida: %s
-  Opzioni account
   Frequenza verifica cartella
   Mai
   Ogni 15 minuti
@@ -405,7 +404,6 @@ Invia segnalazioni di bug, contribuisci con nuove funzionalità e poni domande s
   Ogni 36 minuti
   Ogni 48 minuti
   Ogni 60 minuti
-  Notifica l\'arrivo di nuovi messaggi
   Numero di messaggi da visualizzare
   10 messaggi
   25 messaggi
diff --git a/app/ui/legacy/src/main/res/values-iw/strings.xml b/app/ui/legacy/src/main/res/values-iw/strings.xml
index 85538c861f..329c608300 100644
--- a/app/ui/legacy/src/main/res/values-iw/strings.xml
+++ b/app/ui/legacy/src/main/res/values-iw/strings.xml
@@ -293,7 +293,6 @@
   סיסמא
   סו אימות
   הגדרה לא חוקית: %s
-  אפשרויות חשבון
   אפ פעם
   כל רבע שעה
   כל 30 דקות
@@ -312,7 +311,6 @@
   כל 36 דקות
   כל 48 דקות
   כל 60 דקות
-  הודע לי כאשר מגיע דואר
   מספר הודעות להצגה
   10 הודעות
   25 הודעות
diff --git a/app/ui/legacy/src/main/res/values-ja/strings.xml b/app/ui/legacy/src/main/res/values-ja/strings.xml
index 6f63dbc061..f2c2ed28d4 100644
--- a/app/ui/legacy/src/main/res/values-ja/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ja/strings.xml
@@ -379,7 +379,6 @@ K-9 は大多数のメールクライアントと同様に、ほとんどのフ
   セキュリティ設定
   \"%1$s = %2$s\" は \"%3$s = %4$s\" で無効です
   無効な設定: %s
-  アカウントオプション
   同期フォルダの同期間隔
   しない
   15分毎
@@ -399,7 +398,6 @@ K-9 は大多数のメールクライアントと同様に、ほとんどのフ
   36分毎
   48分毎
   60分毎
-  メール到着時に通知
   受信メールを表示する件数
   10件
   25件
diff --git a/app/ui/legacy/src/main/res/values-ko/strings.xml b/app/ui/legacy/src/main/res/values-ko/strings.xml
index 6b2bf47ade..764ff07dfc 100644
--- a/app/ui/legacy/src/main/res/values-ko/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ko/strings.xml
@@ -314,7 +314,6 @@
   비밀번호
   인증 유형
   잘못된 설정: %s
-  계정 옵션
   폴더 수신 빈도
   하지 않음
   15분마다
@@ -334,7 +333,6 @@
   36분마다
   48분마다
   60분마다
-  메일 도착시 알림
   화면에 보여질 메시지 수
   10 메시지
   25 메시지
diff --git a/app/ui/legacy/src/main/res/values-lt/strings.xml b/app/ui/legacy/src/main/res/values-lt/strings.xml
index bb93a405b5..61d5cd8603 100644
--- a/app/ui/legacy/src/main/res/values-lt/strings.xml
+++ b/app/ui/legacy/src/main/res/values-lt/strings.xml
@@ -377,7 +377,6 @@ Pateikite pranešimus apie klaidas, prisidėkite prie naujų funkcijų kūrimo i
   Tapatumo nustatymas
   \"%1$s = %2$s\" netinka su \"%3$s = %4$s\"
   Netinkamai nustatyta: %s
-  Paskyros parinktys
   Aplanko tikrinimo dažnis
   Niekada
   Kas 15 minučių
@@ -397,7 +396,6 @@ Pateikite pranešimus apie klaidas, prisidėkite prie naujų funkcijų kūrimo i
   Kas 36 minutes
   Kas 48 minutes
   Kas 60 minučių
-  Pranešti apie naujus laiškus
   Rodyti laiškų
   10 laiškų
   25 laiškai
diff --git a/app/ui/legacy/src/main/res/values-lv/strings.xml b/app/ui/legacy/src/main/res/values-lv/strings.xml
index d273e39ad0..b43ddac748 100644
--- a/app/ui/legacy/src/main/res/values-lv/strings.xml
+++ b/app/ui/legacy/src/main/res/values-lv/strings.xml
@@ -384,7 +384,6 @@ pat %d vairāk
   Identitātes pārbaude
   \"%1$s = %2$s\" nav derīgs ar \"%3$s = %4$s\"
   Nederīgi iestatījumi: %s
-  Konta iespējas
   Mapes pārbaudes biežums
   Nekad
   Katras 15 minūtes
@@ -404,7 +403,6 @@ pat %d vairāk
   Katras 36 minūtes
   Katras 48 minūtes
   Katras 60 minūtes
-  Paziņot, kad saņemts jauns pasts
   Vēstuļu skaits, ko parādīt
   10 vēstules
   25 vēstules
diff --git a/app/ui/legacy/src/main/res/values-ml/strings.xml b/app/ui/legacy/src/main/res/values-ml/strings.xml
index bab7c9c7f7..d769f91ba5 100644
--- a/app/ui/legacy/src/main/res/values-ml/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ml/strings.xml
@@ -356,7 +356,6 @@
   പ്രമാണീകരണം
   \"%1$s = %2$s\" \"%3$s = %4$s\" ഉപയോഗിച്ച് സാധുവല്ല
   അസാധുവായ സജ്ജീകരണം: %s
-  അക്കൗണ്ട് ഓപ്ഷനുകൾ
   ഫോൾഡർ വോട്ടെടുപ്പ് ആവൃത്തി
   ഒരിക്കലും
   ഓരോ 15 മിനിറ്റിലും
@@ -376,7 +375,6 @@
   ഓരോ 36 മിനിറ്റിലും
   ഓരോ 48 മിനിറ്റിലും
   ഓരോ 60 മിനിറ്റിലും
-  മെയിൽ വരുമ്പോൾ എന്നെ അറിയിക്കുക
   പ്രദർശിപ്പിക്കേണ്ട സന്ദേശങ്ങളുടെ എണ്ണം
   10 സന്ദേശങ്ങൾ
   25 സന്ദേശങ്ങൾ
diff --git a/app/ui/legacy/src/main/res/values-nb/strings.xml b/app/ui/legacy/src/main/res/values-nb/strings.xml
index fb61266d8b..3fdf1b871a 100644
--- a/app/ui/legacy/src/main/res/values-nb/strings.xml
+++ b/app/ui/legacy/src/main/res/values-nb/strings.xml
@@ -337,7 +337,6 @@ til %d flere
   Autentisering 
   \"%1$s = %2$s\" er ikke gyldig med \"%3$s = %4$s\"
   Ugyldig oppsett: %s
-  Kontoinnstillinger
   Oppdateringsfrekvens for mappen
   Aldri
   Hvert kvarter
@@ -357,7 +356,6 @@ til %d flere
   Hvert 36. minutt
   Hvert 48. minutt
   Hver time
-  Varsle meg når e-post ankommer
   Antall meldinger som skal vises
   10 meldinger
   25 meldinger
diff --git a/app/ui/legacy/src/main/res/values-nl/strings.xml b/app/ui/legacy/src/main/res/values-nl/strings.xml
index ae04630125..9891d6127b 100644
--- a/app/ui/legacy/src/main/res/values-nl/strings.xml
+++ b/app/ui/legacy/src/main/res/values-nl/strings.xml
@@ -377,7 +377,6 @@ Graag foutrapporten sturen, bijdragen voor nieuwe functies en vragen stellen op
   Authenticatietype
   %1$s = %2$s’ is niet geldig met ‘%3$s = %4$s
   Ongeldige instelling: %s
-  Accountopties
   Map-peiling-frequentie
   Nooit
   Elke 15 minuten
@@ -397,7 +396,6 @@ Graag foutrapporten sturen, bijdragen voor nieuwe functies en vragen stellen op
   Elke 36 minuten
   Elke 48 minuten
   Elke 60 minuten
-  Waarschuw wanneer nieuw e-mailbericht binnenkomt
   Aantal berichten om te tonen
   10 berichten
   25 berichten
diff --git a/app/ui/legacy/src/main/res/values-pl/strings.xml b/app/ui/legacy/src/main/res/values-pl/strings.xml
index 4bcb6e21c9..22b3886914 100644
--- a/app/ui/legacy/src/main/res/values-pl/strings.xml
+++ b/app/ui/legacy/src/main/res/values-pl/strings.xml
@@ -386,7 +386,6 @@ Wysłane z urządzenia Android za pomocą K-9 Mail. Proszę wybaczyć moją zwi
   Rodzaj uwierzytelnienia
   \"%1$s = %2$s\" nie jest ważny z \"%3$s = %4$s\"
   Nieprawidłowe ustawienia: %s
-  Opcje konta
   Pobieranie wiadomości
   Nigdy
   Co 15 minut
@@ -406,7 +405,6 @@ Wysłane z urządzenia Android za pomocą K-9 Mail. Proszę wybaczyć moją zwi
   Co 36 minut
   Co 48 minut
   Co 60 minut
-  Powiadamiaj o nowej poczcie
   Wyświetlaj
   10 wiadomości
   25 wiadomości
diff --git a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml
index 542e6552a7..00283726ff 100644
--- a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml
+++ b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml
@@ -383,7 +383,6 @@ Por favor encaminhe relatórios de bugs, contribua com novos recursos e tire dú
   Autenticação
   \"%1$s = %2$s\" não é válido com \"%3$s = %4$s\"
   Configuração inválida: %s
-  Opções da conta
   Frequência de verificação da pasta
   Nunca
   A cada 15 minutos
@@ -403,7 +402,6 @@ Por favor encaminhe relatórios de bugs, contribua com novos recursos e tire dú
   A cada 36 minutos
   A cada 48 minutos
   A cada 60 minutos
-  Notificar quando chegarem novas mensagens
   Número de mensagens a serem exibidas
   10 mensagens
   25 mensagens
diff --git a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml
index 557226d06b..213db22f8c 100644
--- a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml
+++ b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml
@@ -385,7 +385,6 @@ Por favor envie relatórios de falhas, contribua com novas funcionalidades e col
   Autenticação
   \"%1$s = %2$s\" não é válido com \"%3$s = %4$s\"
   Configuração inválida: %s
-  Opções da conta
   Frequência de verificação de pastas
   Nunca
   A cada 15 minutos
@@ -405,7 +404,6 @@ Por favor envie relatórios de falhas, contribua com novas funcionalidades e col
   A cada 36 minutos
   A cada 48 minutos
   A cada 60 minutos
-  Notificar-me na chegada de email
   Número de mensagens para exibição
   10 mensagens
   25 mensagens
diff --git a/app/ui/legacy/src/main/res/values-ro/strings.xml b/app/ui/legacy/src/main/res/values-ro/strings.xml
index 3a222f144f..046c1038ab 100644
--- a/app/ui/legacy/src/main/res/values-ro/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ro/strings.xml
@@ -379,7 +379,6 @@ cel mult încă %d
   Autentificare
   \"%1$s = %2$s\" nu este valabil cu \"%3$s = %4$s
   Configurare greşită : %s
-  Opţiuni cont
   Frecvență interogare dosar
   Niciodată
   La fiecare 15 minute
@@ -399,7 +398,6 @@ cel mult încă %d
   La fiecare 36 de minute
   La fiecare 48 de minute
   La fiecare 60 de minute
-  Notifică-mă când a venit mail
   Număr de mesaje afișate
   10 mesaje
   25 mesaje
diff --git a/app/ui/legacy/src/main/res/values-ru/strings.xml b/app/ui/legacy/src/main/res/values-ru/strings.xml
index 580e828fd3..7ad655b5bd 100644
--- a/app/ui/legacy/src/main/res/values-ru/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ru/strings.xml
@@ -385,7 +385,6 @@ K-9 Mail — почтовик для Android.
   Аутентификация
   «%1$s = %2$s» недействителен для «%3$s = %4$s»
   Неверная настройка: %s
-  Настройки учётной записи
   Промежуток проверки
   Вручную
   15 минут
@@ -405,7 +404,6 @@ K-9 Mail — почтовик для Android.
   36 минут
   48 минут
   1 час
-  Уведомлять о новой почте
   Загружать сообщений
   10 сообщений
   25 сообщений
diff --git a/app/ui/legacy/src/main/res/values-sk/strings.xml b/app/ui/legacy/src/main/res/values-sk/strings.xml
index 4e6fcde02a..78c865ef0b 100644
--- a/app/ui/legacy/src/main/res/values-sk/strings.xml
+++ b/app/ui/legacy/src/main/res/values-sk/strings.xml
@@ -342,7 +342,6 @@ Prosím, nahlasujte prípadné chyby, prispievajte novými funkciami a pýtajte
   Overenie
   \"%1$s = %2$s\" nie je platné s \"%3$s = %4$s\"
   Neplatné nastavenie: %s
-  Možnosti účtu
   Frekvencia synchronizácie priečinkov
   Nikdy
   Každých 15 minút
@@ -362,7 +361,6 @@ Prosím, nahlasujte prípadné chyby, prispievajte novými funkciami a pýtajte
   Každých 36 minút
   Každých 48 minút
   Každých 60 minút
-  Upozorniť ma, keď príde nová správa
   Počet správ na zobrazenie
   10 správ
   25 správ
diff --git a/app/ui/legacy/src/main/res/values-sl/strings.xml b/app/ui/legacy/src/main/res/values-sl/strings.xml
index a14496444f..bae7cc9236 100644
--- a/app/ui/legacy/src/main/res/values-sl/strings.xml
+++ b/app/ui/legacy/src/main/res/values-sl/strings.xml
@@ -381,7 +381,6 @@ dodatnih %d sporočil
   Overjanje
   \"%1$s = %2$s\" *ni veljavno* z \"%3$s = %4$s\"
   Neveljavna nastavitev: %s
-  Možnosti računa
   Pogostost izpraševanja map
   Ročno preverjanje
   Vsakih 15 minut
@@ -401,7 +400,6 @@ dodatnih %d sporočil
   Vsakih 36 minut
   Vsakih 48 minut
   Vsakih 60 minut
-  Obveščaj ob prispetju nove pošte
   Število prikazanih sporočil
   10 sporočil
   25 sporočil
diff --git a/app/ui/legacy/src/main/res/values-sq/strings.xml b/app/ui/legacy/src/main/res/values-sq/strings.xml
index 85b264e35b..5604c3c311 100644
--- a/app/ui/legacy/src/main/res/values-sq/strings.xml
+++ b/app/ui/legacy/src/main/res/values-sq/strings.xml
@@ -382,7 +382,6 @@ Ju lutemi, parashtrim njoftimesh për të meta, kontribute për veçori të reaj
   Mirëfilltësim
   \“%1$s = %2$s\” s\’është i vlefshëm me \“%3$s = %4$s\”
   Rregullim i pavefshëm: %s
-  Mundësi llogarie
   Shpeshti vjeljeje dosjeje
   Kurrë
   Çdo 15 minuta
@@ -402,7 +401,6 @@ Ju lutemi, parashtrim njoftimesh për të meta, kontribute për veçori të reaj
   Çdo 36 minuta
   Çdo 48 minuta
   Çdo 60 minuta
-  Njoftomë kur mbërrin postë
   Numër mesazhesh për shfaqje
   10 mesazhe
   25 mesazhe
diff --git a/app/ui/legacy/src/main/res/values-sr/strings.xml b/app/ui/legacy/src/main/res/values-sr/strings.xml
index 621e7fc0e5..5e324d40ee 100644
--- a/app/ui/legacy/src/main/res/values-sr/strings.xml
+++ b/app/ui/legacy/src/main/res/values-sr/strings.xml
@@ -340,7 +340,6 @@
   Аутентификација
   %1$s = %2$s“ није исправно са „%3$s = %4$s
   Неисправна постава: %s
-  Опције налога
   Проверавање фасцикли
   никад
   на 15 минута
@@ -360,7 +359,6 @@
   на 36 минута
   на 48 минута
   на 60 минута
-  Обавести ме кад стигне пошта
   Број порука за приказ
   10 порука
   25 порука
diff --git a/app/ui/legacy/src/main/res/values-sv/strings.xml b/app/ui/legacy/src/main/res/values-sv/strings.xml
index b0d14cafa1..ddc9edbdec 100644
--- a/app/ui/legacy/src/main/res/values-sv/strings.xml
+++ b/app/ui/legacy/src/main/res/values-sv/strings.xml
@@ -382,7 +382,6 @@ Skicka in felrapporter, bidra med nya funktioner och ställ frågor på
   Autentiseringstyp
   \"%1$s = %2$s\" är inte giltigt med \"%3$s = %4$s\"
   Ogiltig konfiguration: %s
-  Kontoinställningar
   Frekvens för mappkontroll
   Aldrig
   Var 15:e minut
@@ -402,7 +401,6 @@ Skicka in felrapporter, bidra med nya funktioner och ställ frågor på
   Var 36:e minut
   Var 48:e minut
   Var 60:e minut
-  Meddela mig vid ankomst av e-post
   Antal meddelanden att visa
   10 meddelanden
   25 meddelanden
diff --git a/app/ui/legacy/src/main/res/values-tr/strings.xml b/app/ui/legacy/src/main/res/values-tr/strings.xml
index a0543ff7a0..1909bfd3bb 100644
--- a/app/ui/legacy/src/main/res/values-tr/strings.xml
+++ b/app/ui/legacy/src/main/res/values-tr/strings.xml
@@ -368,7 +368,6 @@ Microsoft Exchange ile konuşurken kimi tuhaflıklar yaşadığını lütfen akl
   Kimlik Doğrulama 
   \"%1$s = %2$s\" bununla uyuşmuyor \"%3$s = %4$s\"
   Geçersiz kurulum: %s
-  Hesap seçenekleri
   Klasör bilgi toplama sıklığı
   Asla
   Her 15 dakikada bir
@@ -388,7 +387,6 @@ Microsoft Exchange ile konuşurken kimi tuhaflıklar yaşadığını lütfen akl
   Her 36 dakikada bir
   Her 48 dakikada bir
   Her 60 dakikada bir
-  Posta ulaştığında beni uyar
   Görüntülenecek ileti sayısı
   10 ileti
   25 ileti
diff --git a/app/ui/legacy/src/main/res/values-uk/strings.xml b/app/ui/legacy/src/main/res/values-uk/strings.xml
index 48ef66de60..2fa2020932 100644
--- a/app/ui/legacy/src/main/res/values-uk/strings.xml
+++ b/app/ui/legacy/src/main/res/values-uk/strings.xml
@@ -387,7 +387,6 @@ K-9 Mail — це вільний клієнт електронної пошти
   Метод автентифікації
   \"%1$s = %2$s\" недійсне з \"%3$s = %4$s\"
   Неправильне налаштування: %s
-  Параметри облікового запису
   Частота опитування тек
   Ніколи
   Кожні 15 хвилин
@@ -407,7 +406,6 @@ K-9 Mail — це вільний клієнт електронної пошти
   Кожні 36 хвилин
   Кожні 48 хвилин
   Кожні 60 хвилин
-  Сповіщати мене про отримання нової пошти
   Кількість відображуваних повідомлень
   10 повідомлень
   25 повідомлень
diff --git a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml
index fb0c5c03ed..086f61bd02 100644
--- a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml
+++ b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml
@@ -380,7 +380,6 @@ K-9 Mail 是 Android 上一款功能强大的免费邮件客户端。
   身份验证方法
   \"%1$s = %2$s\" 对于 \"%3$s = %4$s\" 无效
   无效的设置:%s
-  账户选项
   文件夹检查频率
   从不
   15 分钟一次
@@ -400,7 +399,6 @@ K-9 Mail 是 Android 上一款功能强大的免费邮件客户端。
   36 分钟一次
   48 分钟一次
   60 分钟一次
-  有新邮件时通知我
   邮件显示数量
   10 封
   25 封
diff --git a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml
index 406802a377..b81fb7c366 100644
--- a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml
+++ b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml
@@ -380,7 +380,6 @@ K-9 Mail 是 Android 上一款功能強大,免費的電子郵件用戶端。
   身份驗證方法
   %1$s = %2$s」對於「%3$s = %4$s」無效
   無效的設定:%s
-  帳號選項
   信件匣檢查頻率
   不要
   15 分鐘一次
@@ -400,7 +399,6 @@ K-9 Mail 是 Android 上一款功能強大,免費的電子郵件用戶端。
   36 分鐘一次
   48 分鐘一次
   60 分鐘一次
-  有新郵件時通知我
   郵件顯示數量
   10 封
   25 封
diff --git a/app/ui/legacy/src/main/res/values/strings.xml b/app/ui/legacy/src/main/res/values/strings.xml
index ae8074c97e..55a1e161e3 100644
--- a/app/ui/legacy/src/main/res/values/strings.xml
+++ b/app/ui/legacy/src/main/res/values/strings.xml
@@ -455,7 +455,6 @@ Please submit bug reports, contribute new features and ask questions at
 
     Invalid setup: %s
 
-    Account options
 
     Folder poll frequency
     Never
@@ -478,7 +477,6 @@ Please submit bug reports, contribute new features and ask questions at
     Every 48 minutes
     Every 60 minutes
 
-    Notify me when mail arrives
 
     Number of messages to display
     10 messages
-- 
GitLab


From e454ac837a5b05ec24f17999093aba739f39aca5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Fri, 22 Sep 2023 18:33:03 +0200
Subject: [PATCH 67/94] Remove feature flag for new_onboarding

---
 .../featureflag/InMemoryFeatureFlagFactory.kt |  3 +-
 .../java/com/fsck/k9/activity/MessageList.kt  | 13 +-------
 .../fsck/k9/activity/setup/SpinnerOption.java | 33 -------------------
 .../k9/ui/settings/SettingsListFragment.kt    | 26 ++-------------
 4 files changed, 5 insertions(+), 70 deletions(-)
 delete mode 100644 app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/SpinnerOption.java

diff --git a/app/k9mail/src/main/java/com/fsck/k9/featureflag/InMemoryFeatureFlagFactory.kt b/app/k9mail/src/main/java/com/fsck/k9/featureflag/InMemoryFeatureFlagFactory.kt
index 92d040a96e..4d1a923cb9 100644
--- a/app/k9mail/src/main/java/com/fsck/k9/featureflag/InMemoryFeatureFlagFactory.kt
+++ b/app/k9mail/src/main/java/com/fsck/k9/featureflag/InMemoryFeatureFlagFactory.kt
@@ -2,12 +2,11 @@ package com.fsck.k9.featureflag
 
 import app.k9mail.core.featureflag.FeatureFlag
 import app.k9mail.core.featureflag.FeatureFlagFactory
-import app.k9mail.core.featureflag.FeatureFlagKey
 
 class InMemoryFeatureFlagFactory : FeatureFlagFactory {
     override fun createFeatureCatalog(): List {
         return listOf(
-            FeatureFlag(FeatureFlagKey("new_onboarding"), true),
+            // empty
         )
     }
 }
diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageList.kt b/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageList.kt
index 84e6d5135d..8f98f9b647 100644
--- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageList.kt
+++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageList.kt
@@ -28,8 +28,6 @@ import androidx.fragment.app.commit
 import androidx.fragment.app.commitNow
 import app.k9mail.core.android.common.contact.CachingRepository
 import app.k9mail.core.android.common.contact.ContactRepository
-import app.k9mail.core.featureflag.FeatureFlagKey
-import app.k9mail.core.featureflag.FeatureFlagProvider
 import app.k9mail.feature.launcher.FeatureLauncherActivity
 import com.fsck.k9.Account
 import com.fsck.k9.K9
@@ -61,7 +59,6 @@ import com.fsck.k9.ui.messageview.MessageViewContainerFragment
 import com.fsck.k9.ui.messageview.MessageViewContainerFragment.MessageViewContainerListener
 import com.fsck.k9.ui.messageview.MessageViewFragment.MessageViewFragmentListener
 import com.fsck.k9.ui.messageview.PlaceholderFragment
-import com.fsck.k9.ui.onboarding.OnboardingActivity
 import com.fsck.k9.ui.permissions.K9PermissionUiHelper
 import com.fsck.k9.ui.permissions.Permission
 import com.fsck.k9.ui.permissions.PermissionUiHelper
@@ -94,7 +91,6 @@ open class MessageList :
     private val generalSettingsManager: GeneralSettingsManager by inject()
     private val messagingController: MessagingController by inject()
     private val contactRepository: ContactRepository by inject()
-    private val featureFlagProvider: FeatureFlagProvider by inject()
 
     private val permissionUiHelper: PermissionUiHelper = K9PermissionUiHelper(this)
 
@@ -157,14 +153,7 @@ open class MessageList :
         deleteIncompleteAccounts(accounts)
         val hasAccountSetup = accounts.any { it.isFinishedSetup }
         if (!hasAccountSetup) {
-            featureFlagProvider.provide(FeatureFlagKey("new_onboarding")).onEnabled {
-                FeatureLauncherActivity.launchOnboarding(this)
-            }.onDisabled {
-                OnboardingActivity.launch(this)
-            }.onUnavailable {
-                Timber.d("Feature flag 'new_onboarding' is unavailable, falling back to old onboarding")
-                OnboardingActivity.launch(this)
-            }
+            FeatureLauncherActivity.launchOnboarding(this)
             finish()
             return
         }
diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/SpinnerOption.java b/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/SpinnerOption.java
deleted file mode 100644
index 89275b9742..0000000000
--- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/setup/SpinnerOption.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- *
- */
-
-package com.fsck.k9.activity.setup;
-
-import android.widget.Spinner;
-
-public class SpinnerOption {
-    public Object value;
-
-    public String label;
-
-    public static void setSpinnerOptionValue(Spinner spinner, Object value) {
-        for (int i = 0, count = spinner.getCount(); i < count; i++) {
-            SpinnerOption so = (SpinnerOption)spinner.getItemAtPosition(i);
-            if (so.value.equals(value)) {
-                spinner.setSelection(i, true);
-                return;
-            }
-        }
-    }
-
-    public SpinnerOption(Object value, String label) {
-        this.value = value;
-        this.label = label;
-    }
-
-    @Override
-    public String toString() {
-        return label;
-    }
-}
diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/SettingsListFragment.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/SettingsListFragment.kt
index 1dffceea9e..fdbaaaa537 100644
--- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/SettingsListFragment.kt
+++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/SettingsListFragment.kt
@@ -11,13 +11,9 @@ import android.widget.Toast
 import androidx.annotation.AttrRes
 import androidx.annotation.IdRes
 import androidx.fragment.app.Fragment
-import androidx.navigation.fragment.findNavController
 import androidx.recyclerview.widget.ItemTouchHelper
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
-import app.k9mail.core.featureflag.FeatureFlagKey
-import app.k9mail.core.featureflag.FeatureFlagProvider
-import app.k9mail.core.featureflag.FeatureFlagResult
 import app.k9mail.feature.launcher.FeatureLauncherActivity
 import com.fsck.k9.Account
 import com.fsck.k9.ui.R
@@ -32,13 +28,10 @@ import com.mikepenz.fastadapter.adapters.ItemAdapter
 import com.mikepenz.fastadapter.drag.ItemTouchCallback
 import com.mikepenz.fastadapter.drag.SimpleDragCallback
 import com.mikepenz.fastadapter.utils.DragDropUtil
-import org.koin.android.ext.android.inject
 import org.koin.androidx.viewmodel.ext.android.viewModel
-import timber.log.Timber
 
 class SettingsListFragment : Fragment(), ItemTouchCallback {
     private val viewModel: SettingsViewModel by viewModel()
-    private val featureFlagProvider: FeatureFlagProvider by inject()
 
     private lateinit var itemAdapter: ItemAdapter
 
@@ -157,12 +150,9 @@ class SettingsListFragment : Fragment(), ItemTouchCallback {
             is UrlActionItem -> openUrl(item.url)
             is SettingsActionItem -> {
                 if (
-                    item.navigationAction == R.id.action_settingsListScreen_to_addAccountScreen &&
-                    featureFlagProvider.provide(FeatureFlagKey("new_onboarding")) is FeatureFlagResult.Enabled
+                    item.navigationAction == R.id.action_settingsListScreen_to_addAccountScreen
                 ) {
                     FeatureLauncherActivity.launchSetupAccount(requireActivity())
-                } else {
-                    findNavController().navigate(item.navigationAction)
                 }
             }
         }
@@ -182,19 +172,9 @@ class SettingsListFragment : Fragment(), ItemTouchCallback {
     }
 
     private fun launchOnboarding() {
-        featureFlagProvider.provide(FeatureFlagKey("new_onboarding")).onEnabled {
-            FeatureLauncherActivity.launchOnboarding(requireActivity())
-        }.onDisabled {
-            launchOldOnboarding()
-        }.onUnavailable {
-            Timber.d("Feature flag 'new_onboarding' is unavailable, falling back to old onboarding")
-            launchOldOnboarding()
-        }
-        requireActivity().finishAffinity()
-    }
+        FeatureLauncherActivity.launchOnboarding(requireActivity())
 
-    private fun launchOldOnboarding() {
-        findNavController().navigate(R.id.action_settingsListScreen_to_onboardingScreen)
+        requireActivity().finishAffinity()
     }
 
     private fun buildSettingsList(block: SettingsListBuilder.() -> Unit): List {
-- 
GitLab


From 7b189afa6e311d3bd11ff5f0c22d6119bf2370f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= 
Date: Fri, 22 Sep 2023 18:39:24 +0200
Subject: [PATCH 68/94] Remove OnboardingActivity

---
 app/k9mail/src/main/AndroidManifest.xml       |  4 --
 .../k9/ui/onboarding/OnboardingActivity.kt    | 44 ------------------
 .../main/res/layout/activity_onboarding.xml   | 22 ---------
 .../res/navigation/navigation_onboarding.xml  | 45 -------------------
 .../res/navigation/navigation_settings.xml    | 10 -----
 5 files changed, 125 deletions(-)
 delete mode 100644 app/ui/legacy/src/main/java/com/fsck/k9/ui/onboarding/OnboardingActivity.kt
 delete mode 100644 app/ui/legacy/src/main/res/layout/activity_onboarding.xml
 delete mode 100644 app/ui/legacy/src/main/res/navigation/navigation_onboarding.xml

diff --git a/app/k9mail/src/main/AndroidManifest.xml b/app/k9mail/src/main/AndroidManifest.xml
index cad908a1b4..a10fba49ee 100644
--- a/app/k9mail/src/main/AndroidManifest.xml
+++ b/app/k9mail/src/main/AndroidManifest.xml
@@ -60,10 +60,6 @@
         
 
-        
-
         
-
-
-    
-
-    
-
-
diff --git a/app/ui/legacy/src/main/res/navigation/navigation_onboarding.xml b/app/ui/legacy/src/main/res/navigation/navigation_onboarding.xml
deleted file mode 100644
index dcddab1586..0000000000
--- a/app/ui/legacy/src/main/res/navigation/navigation_onboarding.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-    
-
-        
-
-        
-
-        
-
-    
-
-    
-
-    
-
-    
-
-
diff --git a/app/ui/legacy/src/main/res/navigation/navigation_settings.xml b/app/ui/legacy/src/main/res/navigation/navigation_settings.xml
index a7ffc12201..f4d2c2a2ed 100644
--- a/app/ui/legacy/src/main/res/navigation/navigation_settings.xml
+++ b/app/ui/legacy/src/main/res/navigation/navigation_settings.xml
@@ -11,10 +11,6 @@
         android:label="@string/prefs_title"
         tools:layout="@layout/fragment_settings_list">
 
-        
-
         
@@ -36,12 +32,6 @@
             app:destination="@id/settingsImportScreen" />
     
 
-    
-
     
Date: Fri, 22 Sep 2023 18:45:57 +0200
Subject: [PATCH 69/94] Remove WelcomeFragment

---
 .../fsck/k9/ui/onboarding/WelcomeFragment.kt  | 57 -------------------
 .../res/layout/fragment_welcome_message.xml   | 38 -------------
 .../legacy/src/main/res/values-ar/strings.xml | 33 +----------
 .../legacy/src/main/res/values-be/strings.xml | 32 +----------
 .../legacy/src/main/res/values-bg/strings.xml | 33 +----------
 .../legacy/src/main/res/values-br/strings.xml | 33 +----------
 .../legacy/src/main/res/values-ca/strings.xml | 33 +----------
 .../legacy/src/main/res/values-cs/strings.xml | 33 +----------
 .../legacy/src/main/res/values-cy/strings.xml | 34 +----------
 .../legacy/src/main/res/values-da/strings.xml | 33 +----------
 .../legacy/src/main/res/values-de/strings.xml | 33 +----------
 .../legacy/src/main/res/values-el/strings.xml | 34 +----------
 .../src/main/res/values-en-rGB/strings.xml    |  1 -
 .../legacy/src/main/res/values-eo/strings.xml | 32 +----------
 .../legacy/src/main/res/values-es/strings.xml | 32 +----------
 .../legacy/src/main/res/values-et/strings.xml | 34 +----------
 .../legacy/src/main/res/values-eu/strings.xml | 33 +----------
 .../legacy/src/main/res/values-fa/strings.xml | 33 +----------
 .../legacy/src/main/res/values-fi/strings.xml | 33 +----------
 .../legacy/src/main/res/values-fr/strings.xml | 33 +----------
 .../legacy/src/main/res/values-fy/strings.xml | 29 +---------
 .../legacy/src/main/res/values-gd/strings.xml |  5 +-
 .../legacy/src/main/res/values-gl/strings.xml | 34 +----------
 .../legacy/src/main/res/values-hr/strings.xml |  2 -
 .../legacy/src/main/res/values-hu/strings.xml | 32 +----------
 .../legacy/src/main/res/values-in/strings.xml | 33 +----------
 .../legacy/src/main/res/values-is/strings.xml | 33 +----------
 .../legacy/src/main/res/values-it/strings.xml | 34 +----------
 .../legacy/src/main/res/values-iw/strings.xml |  4 +-
 .../legacy/src/main/res/values-ja/strings.xml | 34 +----------
 .../legacy/src/main/res/values-ko/strings.xml |  2 -
 .../legacy/src/main/res/values-lt/strings.xml | 34 +----------
 .../legacy/src/main/res/values-lv/strings.xml | 33 +----------
 .../legacy/src/main/res/values-ml/strings.xml | 33 +----------
 .../legacy/src/main/res/values-nb/strings.xml | 34 +----------
 .../legacy/src/main/res/values-nl/strings.xml | 29 +---------
 .../legacy/src/main/res/values-pl/strings.xml | 33 +----------
 .../src/main/res/values-pt-rBR/strings.xml    | 33 +----------
 .../src/main/res/values-pt-rPT/strings.xml    | 34 +----------
 .../legacy/src/main/res/values-ro/strings.xml | 33 +----------
 .../legacy/src/main/res/values-ru/strings.xml | 33 +----------
 .../legacy/src/main/res/values-sk/strings.xml | 34 +----------
 .../legacy/src/main/res/values-sl/strings.xml | 33 +----------
 .../legacy/src/main/res/values-sq/strings.xml | 34 +----------
 .../legacy/src/main/res/values-sr/strings.xml | 33 +----------
 .../legacy/src/main/res/values-sv/strings.xml | 33 +----------
 .../legacy/src/main/res/values-tr/strings.xml | 33 +----------
 .../legacy/src/main/res/values-uk/strings.xml | 34 +----------
 .../src/main/res/values-zh-rCN/strings.xml    | 34 +----------
 .../src/main/res/values-zh-rTW/strings.xml    | 34 +----------
 app/ui/legacy/src/main/res/values/strings.xml | 34 -----------
 51 files changed, 45 insertions(+), 1519 deletions(-)
 delete mode 100644 app/ui/legacy/src/main/java/com/fsck/k9/ui/onboarding/WelcomeFragment.kt
 delete mode 100644 app/ui/legacy/src/main/res/layout/fragment_welcome_message.xml

diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/onboarding/WelcomeFragment.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/onboarding/WelcomeFragment.kt
deleted file mode 100644
index 3ce5043759..0000000000
--- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/onboarding/WelcomeFragment.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.fsck.k9.ui.onboarding
-
-import android.os.Bundle
-import android.text.method.LinkMovementMethod
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.fragment.app.Fragment
-import androidx.navigation.fragment.findNavController
-import com.fsck.k9.ui.R
-import com.fsck.k9.ui.helper.HtmlToSpanned
-import com.fsck.k9.ui.observeNotNull
-import com.fsck.k9.ui.settings.import.SettingsImportResultViewModel
-import com.fsck.k9.ui.settings.import.SettingsImportSuccess
-import org.koin.android.ext.android.inject
-import org.koin.androidx.viewmodel.ext.android.activityViewModel
-
-class WelcomeFragment : Fragment() {
-    private val htmlToSpanned: HtmlToSpanned by inject()
-    private val importResultViewModel: SettingsImportResultViewModel by activityViewModel()
-
-    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
-        return inflater.inflate(R.layout.fragment_welcome_message, container, false)
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-
-        val welcome: TextView = view.findViewById(R.id.welcome_message)
-        welcome.text = htmlToSpanned.convert(getString(R.string.accounts_welcome))
-        welcome.movementMethod = LinkMovementMethod.getInstance()
-
-        view.findViewById(R.id.next).setOnClickListener { launchAccountSetup() }
-        view.findViewById(R.id.import_settings).setOnClickListener { launchImportSettings() }
-
-        importResultViewModel.settingsImportResult.observeNotNull(this) {
-            if (it == SettingsImportSuccess) {
-                launchMessageList()
-            }
-        }
-    }
-
-    private fun launchAccountSetup() {
-        findNavController().navigate(R.id.action_welcomeScreen_to_addAccountScreen)
-        requireActivity().finish()
-    }
-
-    private fun launchImportSettings() {
-        findNavController().navigate(R.id.action_welcomeScreen_to_settingsImportScreen)
-    }
-
-    private fun launchMessageList() {
-        findNavController().navigate(R.id.action_welcomeScreen_to_messageListScreen)
-        requireActivity().finish()
-    }
-}
diff --git a/app/ui/legacy/src/main/res/layout/fragment_welcome_message.xml b/app/ui/legacy/src/main/res/layout/fragment_welcome_message.xml
deleted file mode 100644
index 07dacc29a9..0000000000
--- a/app/ui/legacy/src/main/res/layout/fragment_welcome_message.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-    
-
-        
-
-            
-
-            
-        
-    
-
-    
-
-
diff --git a/app/ui/legacy/src/main/res/values-ar/strings.xml b/app/ui/legacy/src/main/res/values-ar/strings.xml
index 4e5c0ec37c..c9bfb99d0f 100644
--- a/app/ui/legacy/src/main/res/values-ar/strings.xml
+++ b/app/ui/legacy/src/main/res/values-ar/strings.xml
@@ -28,38 +28,7 @@
   اكتشف الجديد في هذا الإصدار
   
   عرض
-  
-  أهلا بكم في بريد K-9
-  
-تطبيق K-9 عبارة عن تطبيق بريد متقدم لنظام أندرويد
-

-حصائصة المُحسّنة تشمل: -

-
    -
  • دفع البريد من خلال IMAP IDLE
  • -
  • أداء أفضل
  • -
  • إعادة تعبئة الرسائل
  • -
  • توقيع البريد
  • -
  • نسخة مخفية لنفسك
  • -
  • الإشتراك في المجلدات
  • -
  • مزامنة جميع المجلدات
  • -
  • إعدادات عنوان الرد
  • -
  • اختصارات لوحة المفاتيح
  • -
  • دعم أفضل لبروتوكول IMAP
  • -
  • حفظ المرفقات الى بطاقة الذاكرة
  • -
  • تفريغ المحذوفات
  • -
  • تصنيف الرسائل
  • -
  • … والمزيد
  • -
-

-يرجى الملاحظة أن K-9 لا يدعم معظم حسابات Hotmail المجانية وكما هو الحال في معظم برامج البريد، هذا البرنامج يعاني من مشاكل غريبة مع Microsoft Exchange. -

-يرجى التبليغ عن الأخطاء، المساهمة في الكود، أو طرح الأسئلة على الرابط: -https://github.com/k9mail/k-9/ -

- ]]> - + -- \nتم الإرسال من هاتفي الأندرويد بواسطة برنامج K-9. أعتذر عن الإيجاز. سيُحذف الحساب \"%s\" من الحسابات في K-9. diff --git a/app/ui/legacy/src/main/res/values-be/strings.xml b/app/ui/legacy/src/main/res/values-be/strings.xml index 939a835515..1aeb5545aa 100644 --- a/app/ui/legacy/src/main/res/values-be/strings.xml +++ b/app/ui/legacy/src/main/res/values-be/strings.xml @@ -28,37 +28,7 @@ Даведайцеся, што новага ў гэтым выпуску Праглядзець - - Вітаем у K-9 - -K-9 Mail - шматфункцыянальны свабодны паштовы кліент для Android. -

-Магчымасці: -

-
    -
  • рush-апавяшчэнні
  • -
  • хуткая праца
  • -
  • перасылка лістоў
  • -
  • подпісы
  • -
  • схаваная копія для сябе
  • -
  • падпіска на каталогі
  • -
  • сінхранізацыя ўсіх каталогаў
  • -
  • адрас для адказу
  • -
  • гарачыя клавішы
  • -
  • палепшаная падтрымка IMAP
  • -
  • захаванне ўкладзеных файлаў
  • -
  • ачыстка сметніцы
  • -
  • сартаванне лістоў
  • -
  • …і іншае
  • -
-

-Калі ласка, звярніце ўвагу, што K-9 не падтрымлівае бясплатныя акаўнты Hotmail і не цалкам падтрымлівае Microsoft Exchange. -

-Пляцоўка распрацоўвання: -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nАдпраўлена з маёй прылады праз K-9 Mail. Выбачайце за сцісласць. Акаўнт \"%s\" будзе выдалены з K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-bg/strings.xml b/app/ui/legacy/src/main/res/values-bg/strings.xml index ddcef0e607..b178cd08b6 100644 --- a/app/ui/legacy/src/main/res/values-bg/strings.xml +++ b/app/ui/legacy/src/main/res/values-bg/strings.xml @@ -24,38 +24,7 @@ Разбери какво ново в тази варсия - - Добре дошли в K-9 Mail - -K-9 Mail е мощен, безплатен имейл клиент за Андроид. -

-Подобрените функции включват: -

-
    -
  • Push mail използвайки IMAP IDLE
  • -
  • По-добра производителност
  • -
  • Преместване на съобщения
  • -
  • Имейл подписи
  • -
  • Bcc до себе си
  • -
  • Абонамент за папки
  • -
  • Синхронизиране на всички папки
  • -
  • Конфигурация на адреса за връщане
  • -
  • Кратки клавишни комбинации
  • -
  • По-добра подръжка на IMAP
  • -
  • Запазване на прикачени файлове на SD
  • -
  • Изпразване на кошчето
  • -
  • Сортиране на съобщения
  • -
  • …и още
  • -
-

-Моля знайте, че K-9 не подържа повечето безплатни Hotmail профили и, че както повечето имейл приложения има няколко странности, когато говори с Microsoft Exchange. -

-Моля изпращайте доклади за бъгове, допринасяйте за нови функции и задавайте въпроси на -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nИзпратено от моето Андроид у-во чрез K-9 Mail. Моля да ме извините за краткия ми изказ. Акаунтът \"%s\" ще бъде премахнат от K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-br/strings.xml b/app/ui/legacy/src/main/res/values-br/strings.xml index 6cb15c4ddd..8bf9211b61 100644 --- a/app/ui/legacy/src/main/res/values-br/strings.xml +++ b/app/ui/legacy/src/main/res/values-br/strings.xml @@ -13,38 +13,7 @@ Lañvaz - - Donemat war K-9 Mail - -K-9 Mail a zo un arval posteloù digoust galloudus evit Android -

-Kavet e vez e-touez e geweriusterioù: -

-
    -
  • Bountañ posteloù gant IMAP IDLE
  • -
  • Digonusted gwelloc’h
  • -
  • Adleuniadenn kemennadennoù
  • -
  • Sinadurioù postel
  • -
  • Bcc-to-self
  • -
  • Koumanant da deuliadoù
  • -
  • Goubredañ d’an holl deuliadoù
  • -
  • Kefluniadur ar chomlec’h daskor
  • -
  • Berradennoù klavier
  • -
  • Skor IMAP gwelloc’h
  • -
  • Enrollañ kenstagadennoù d’ar gartenn SD
  • -
  • Goullonderiñ ar c’hest
  • -
  • Urzhiañ ar c’hemennadennoù
  • -
  • …ha muioc’h c’hoazh
  • -
-

-K- ne skor ket lodenn vrasañ ar c’hontoù Hotmail digoust hag evel loden vrasañ an arvaloù postel eo diaes dezhañ eskemm gant Microsoft Exchange. -

-Danevellit beugoù, kenlabourit war keweriusterioù nevez ha savit goulennoù war -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nKaset eus ma fellgomzer Android gant K-9 Mail. Dilamet e vo ar gont \"%s\" eus K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-ca/strings.xml b/app/ui/legacy/src/main/res/values-ca/strings.xml index e1a02b2a85..8fe917346c 100644 --- a/app/ui/legacy/src/main/res/values-ca/strings.xml +++ b/app/ui/legacy/src/main/res/values-ca/strings.xml @@ -28,38 +28,7 @@ Esbrineu les novetats d’aquesta versió. Vista - - Us donem la benvinguda al K-9 Mail - -El K-9 Mail és un potent client de correu de codi lliure per a Android. -

-Les característiques més destacables són les següents: -

-
    -
  • Tramet correu fent servir IMAP IDLE
  • -
  • Millor rendiment
  • -
  • Rearxivament de missatges
  • -
  • Signatures de correu
  • -
  • Còpia oculta a un mateix
  • -
  • Subscripció a carpetes
  • -
  • Sincronització de totes les carpetes
  • -
  • Configuració de l\'adreça de resposta
  • -
  • Dreceres de teclat
  • -
  • Millor suport per a IMAP
  • -
  • Possibilitat de desar els adjunts a la SD
  • -
  • Buidatge de la paperera
  • -
  • Ordenació de missatges
  • -
  • … i molt més
  • -
-

-Si us plau, tingueu en compte que el K-9 no admet la majoria de comptes gratuïts de Hotmail i que, com la majoria d\'altres clients de correu, té alguns problemes per interactuar amb el Microsoft Exchange. -

-Si us plau, envieu informes d\'errors, contribuïu-hi amb noves millores i feu preguntes a -https://github.com/k9mail/k-9/. -

-]]>
- + -- \nEnviat des del meu dispositiu Android amb el K-9 Mail. Disculpeu la brevetat. El compte \"%s\" s\'eliminarà del K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-cs/strings.xml b/app/ui/legacy/src/main/res/values-cs/strings.xml index e001863a96..07e9d33b5f 100644 --- a/app/ui/legacy/src/main/res/values-cs/strings.xml +++ b/app/ui/legacy/src/main/res/values-cs/strings.xml @@ -28,38 +28,7 @@ Zjistěte, co je v tomto vydání nového Zobrazit - - Vítejte v K-9 Mail - -K-9 Mail je všestranný e-mailový klient pro Android. -

-Vylepšené funkce zahrnují: -

-
    -
  • Push mail pomocí IMAP IDLE
  • -
  • Lepší výkon
  • -
  • Vyplňování zpráv
  • -
  • Podpisy zpráv
  • -
  • Skryté kopie sobě
  • -
  • Odebírané složky
  • -
  • Synchronizace všech složek
  • -
  • Nastavení zpáteční adresy
  • -
  • Klávesové zkratky
  • -
  • Lepší podpora IMAP
  • -
  • Ukládání příloh na SD kartu
  • -
  • Vysypání koše
  • -
  • Řazení zpráv
  • -
  • …a další
  • -
-

-K-9 nepodporuje většinu bezplatných účtů u Hotmail a jako mnoho poštovních klientů vykazuje zvláštnosti při komunikaci s Microsoft Exchange. -

-Hlášení o chyb, úpravy pro nové funkce a dotazy zadávejte prostřednictvím -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nOdesláno aplikací K-9 Mail ze systému Android. Omluvte prosím moji stručnost. Účet \"%s\" bude odstraněn z K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-cy/strings.xml b/app/ui/legacy/src/main/res/values-cy/strings.xml index d05442af57..e232399e16 100644 --- a/app/ui/legacy/src/main/res/values-cy/strings.xml +++ b/app/ui/legacy/src/main/res/values-cy/strings.xml @@ -27,39 +27,7 @@ Darganfod beth sy\'n newydd yn y diweddariad hwn - - Croeso i K-9 Mail - -Mae K-9 Mail yn gleient e-bost pwerus ar gyfer Android. -

-Mae ei nodweddion gwell yn cynnwys: -

    -
  • Gwthio negeseuon gydag IMAP IDLE
  • -
  • Gwell perfformiad
  • -
  • Ail-drefnu negeseuon
  • -
  • Llofnodion e-bost
  • -
  • BCC i dy hun
  • -
  • Tanysgrifio fesul ffolder
  • -
  • Cysoni pob ffolder
  • -
  • Ffufweddu cyfeiriad ateb
  • -
  • Bysellau brys
  • -
  • Gwell cefnogaeth IMAP
  • -
  • Cadw atodiadau i SD
  • -
  • Gwagio\'r sbwriel
  • -
  • Trefnu negeseuon
  • -
  • …a mwy
  • -
-

-Noder nad yw K-9 yn cyd-fynd a mwyafrif cyfrifon am ddim Hotmail ac, fel nifer o gleientiaid e-bost, mae rhai pethau\'n gweithio\'n od wrth drafod â Microsoft Exchange. - -Mae\'r ap yn dibynnu ar Android ei hun ar gyfer peth cynnwys. Yn anffodus, nid yw fersiynau swyddogol o Android yn cefnogi\'r Gymraeg ac felly fe weli rywfaint o Saesneg yn yr ap, e.e. \"5 minutes ago\" yn lle \"5 munud yn ôl\", \"Dec\" yn lle \"Rhag\". -

-Plîs rho wybod am unrhyw wallau, syniadau am nodweddion newydd, neu ofyn cwestiynnau yma: -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nAnfonwyd gyda K-9 Mail ar Android\n - yr ap ebost cyntaf yn y Gymraeg. Caiff y cyfrif \"%s\" ei dynnu o K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-da/strings.xml b/app/ui/legacy/src/main/res/values-da/strings.xml index 3ba2aa0aa2..bbf10a7ffd 100644 --- a/app/ui/legacy/src/main/res/values-da/strings.xml +++ b/app/ui/legacy/src/main/res/values-da/strings.xml @@ -28,38 +28,7 @@ Find ud af hvad der er nyt i denne version Vis - - Velkommen til K-9 Mail - -K-9 Mail er en slagkraftig gratis mail-klient til Android. -

-Dens forbedrede funktioner omfatter: -

-
    -
  • \"Push mail\" ved hjælp af IMAP IDLE
  • -
  • Bedre ydeevne
  • -
  • Genarkivering af meddelelser
  • -
  • Signaturer
  • -
  • Bcc-til-dig-selv
  • -
  • Mappeabonnementer
  • -
  • Synkronisering af alle mapper
  • -
  • Konfiguration af Retur-adresse
  • -
  • Tastaturgenveje
  • -
  • Bedre IMAP-understøttelse
  • -
  • Gemning af vedhæftninger på SD-kort
  • -
  • Tømning af papirkurv
  • -
  • Sortering af meddelelser
  • -
  • …og mere
  • -
-

-Bemærk, at K-9 ikke understøtter de fleste gratis Hotmail-konti, og ligesom mange mail-klienter, har nogle uhensigtsmæssigheder, når den kommunikerer med Microsoft Exchange. -

-Rapporter venligst fejl, forslag til nye funktioner eller stil spørgsmål på: -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nDette er sendt fra min mobiltelefon. Undskyld at jeg fatter mig i korthed. Kontoen \"%s\" vil blive fjernet fra K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-de/strings.xml b/app/ui/legacy/src/main/res/values-de/strings.xml index 036cdc8dc5..30ddb82a80 100644 --- a/app/ui/legacy/src/main/res/values-de/strings.xml +++ b/app/ui/legacy/src/main/res/values-de/strings.xml @@ -28,38 +28,7 @@ Finde heraus, was es Neues in diesem Release gibt Ansehen - - Willkommen bei K-9 Mail - -K-9 Mail ist ein leistungsstarker, freier E-Mail-Client für Android. -

-Seine verbesserten Funktionen beinhalten: -

-
    -
  • Push-Mail unter Verwendung von IMAP IDLE
  • -
  • Bessere Leistung
  • -
  • Nachrichtenneuordnung
  • -
  • E-Mail-Signaturen
  • -
  • BCC an sich selbst
  • -
  • Ordnerabonnements
  • -
  • Synchronisation aller Ordner
  • -
  • Rücksendeadresskonfiguration
  • -
  • Tastaturkürzel
  • -
  • Bessere IMAP-Unterstützung
  • -
  • Speichern von Anhängen auf SD
  • -
  • Papierkorb leeren
  • -
  • Nachrichtensortierung
  • -
  • …und weitere
  • -
-

-Bitte beachte, dass K-9 die meisten kostenlosen Hotmail-Konten nicht unterstützt und, wie viele andere E-Mail-Clients, einige Macken bei der Kommunikation mit Microsoft Exchange hat. -

-Bitte sende Fehlerberichte, Ideen für neue Funktionen und stelle Fragen an -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nDiese Nachricht wurde von meinem Android-Gerät mit K-9 Mail gesendet. Das Konto \"%s\" wird aus K-9 Mail entfernt. diff --git a/app/ui/legacy/src/main/res/values-el/strings.xml b/app/ui/legacy/src/main/res/values-el/strings.xml index 8af04d0ccb..4a02f4a128 100644 --- a/app/ui/legacy/src/main/res/values-el/strings.xml +++ b/app/ui/legacy/src/main/res/values-el/strings.xml @@ -28,39 +28,7 @@ Δείτε τι έχει αλλάξει σε αυτή την έκδοση Προβολή - - Καλώς ορίσατε στο K-9 Mail - -Το K-9 Mail είναι μία ισχυρή δωρεάν εφαρμογή ηλεκτρονικού ταχυδρομείου για το Android. -

-Τα βελτιωμένα χαρακτηριστικά του περιλαμβάνουν: -

-
    -
  • Ταχυδρομείο με σπρώξιμο (push mail) με χρήση IMAP IDLE
  • -
  • Καλύτερες επιδόσεις
  • -
  • Επαναταξινόμηση μηνύματος
  • -
  • Υπογραφές ηλεκτρονικού ταχυδρομείου
  • -
  • Ιδιωτική κοινοποίηση (bcc) προς εαυτό
  • -
  • Συνδρομές σε φακέλους
  • -
  • Συγχρονισμός όλων των φακέλων
  • -
  • Ρύθμιση διεύθυνσης επιστροφής
  • -
  • Συντομεύσεις πληκτρολογίου
  • -
  • Καλύτερη υποστήριξη IMAP
  • -
  • Αποθήκευση συνημμένων στην κάρτα αποθήκευσης
  • -
  • Άδειασμα απορριμάτων
  • -
  • Ταξινόμηση μηνυμάτων
  • -
  • …και άλλα
  • -
-

-Να σημειωθεί ότι το K-9 δεν υποστηρίζει τους περισσότερους δωρεάν λογαριασμούς Hotmail και, -όπως οι περισσότερες εφαρμογές ηλεκτρονικού ταχυδρομείου, έχει θεματάκια με το Microsoft Exchange. -

-Παρακαλώ υποβάλετε αναφορές σφαλμάτων, συμβάλλετε νέα χαρακτηριστικά και θέστε ερωτήσεις στο -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nΣταλμένο από τη συσκευή μου Android με το K-9 Mail. Παρακαλώ συγχωρήστε την ολιγολογία μου. Ο λογαριασμός \'%s\' θα διαγραφεί από το K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-en-rGB/strings.xml b/app/ui/legacy/src/main/res/values-en-rGB/strings.xml index 8069bd74d9..e392f87d14 100644 --- a/app/ui/legacy/src/main/res/values-en-rGB/strings.xml +++ b/app/ui/legacy/src/main/res/values-en-rGB/strings.xml @@ -9,7 +9,6 @@ - diff --git a/app/ui/legacy/src/main/res/values-eo/strings.xml b/app/ui/legacy/src/main/res/values-eo/strings.xml index a6d24a1152..40ff007c9a 100644 --- a/app/ui/legacy/src/main/res/values-eo/strings.xml +++ b/app/ui/legacy/src/main/res/values-eo/strings.xml @@ -25,37 +25,7 @@ Kio estas nova en tiu ĉi versio - - Bonvenon al K-9 Retpoŝtilo - -K-9 Retpoŝtilo estas potenca libera retpoŝtilo por Android. -

-Jen kelkaj distingaj ebloj de ĝi: -

-
    -
  • Puŝ-retleteroj per IMAP IDLE
  • -
  • Pli bona rendimento
  • -
  • Rearanĝado de mesaĝoj
  • -
  • Subskriboj de retleteroj
  • -
  • Kaŝkopio al si mem
  • -
  • Aboni mesaĝujojn
  • -
  • Samtempigi ĉiujn mesaĝujojn
  • -
  • Agordebla responda adreso
  • -
  • Fulmoklavoj
  • -
  • Pli bona subteno por IMAP
  • -
  • Konservi kunsendaĵojn al SD-karto
  • -
  • Malplenigi rubujon
  • -
  • Ordigi mesaĝojn
  • -
  • …kaj pli
  • -
-

-Bonvolu rimarki, ke K-9 Retpoŝtilo ne subtenas plejparton da senpagaj Hotmail-kontoj kaj simile al aliaj retpoŝtiloj, ĝi povas esti kapricema dum komunikado kun Microsoft Exchange. -

-Bonvolu raporti erarojn, kontribui novajn eblojn kaj peti pri novaj funkcioj per nia retpaĝo https://github.com/k9mail/k-9/. -

-]]>
- + -- \nSendita per K-9 Retpoŝtilo. Bonvolu pardoni min por skribi mallonge. La konto \"%s\" estos forigita el K-9 Retpoŝtilo. diff --git a/app/ui/legacy/src/main/res/values-es/strings.xml b/app/ui/legacy/src/main/res/values-es/strings.xml index 0b02124379..8d55dc98bd 100644 --- a/app/ui/legacy/src/main/res/values-es/strings.xml +++ b/app/ui/legacy/src/main/res/values-es/strings.xml @@ -28,37 +28,7 @@ Descubre las novedades de esta versión Leer - - Te damos la bienvenida a K-9 Mail - -K-9 Mail es un cliente de correo rápido, libre y potente para Android. -

-Sus características más destacadas son: -

-
    -
  • Notificaciones rápidas («push») usando IMAP IDLE
  • -
  • Un rendimiento superior
  • -
  • Archivado de mensajes
  • -
  • Firmas de correo
  • -
  • Cco-a-sí-mismo
  • -
  • Suscripciones a carpetas
  • -
  • Sincronización de todas las carpetas
  • -
  • Configuración de la dirección de respuesta
  • -
  • Atajos del teclado
  • -
  • Características avanzadas para IMAP
  • -
  • Guardar adjuntos a la tarjeta SD
  • -
  • Vaciar la papelera
  • -
  • Ordenación de mensajes
  • -
  • …y mucho más
  • -
-

-Ten en cuenta que K-9 no funciona bien con la mayor parte de las cuentas gratuitas de Hotmail, y (como tantos otros clientes de correo) puede tener alguna dificultad al comunicarse con servidores de Microsoft Exchange. -

-Puedes informar de fallos, contribuir con su desarrollo y hacer preguntas en https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nEnviado desde mi dispositivo Android con K-9 Mail. Por favor, disculpa mi brevedad. La cuenta \"%s\" será eliminada de K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-et/strings.xml b/app/ui/legacy/src/main/res/values-et/strings.xml index 2c616af7d8..f28e76432c 100644 --- a/app/ui/legacy/src/main/res/values-et/strings.xml +++ b/app/ui/legacy/src/main/res/values-et/strings.xml @@ -28,39 +28,7 @@ Vaata mis on selles versioonis muutunud Vaata - - Tere tulemast K-9 Maili - -K-9 Mail on tõhus tasuta e-posti klient Androidile. -

-Rakendus pakub muu hulgas selliseid uuenenud võimalusi: -

-
    -
  • tõuketeenus, mille aluseks on IMAP IDLE
  • -
  • parem jõudlus
  • -
  • kirjade ümberpaigutamine
  • -
  • kirjade allkirjad
  • -
  • pimekoopia ehk bcc iseendale
  • -
  • IMAP\'i kaustade tellimine
  • -
  • kõikide kaustade sünkroniserimine
  • -
  • saatja-aadresside seadistamine
  • -
  • kiirklahvid
  • -
  • parandatud IMAP\'i tugi
  • -
  • manuste salvestamine SD-kaardile
  • -
  • prügikasti tühjendamine
  • -
  • kirjade sortimine
  • -
  • …ja palju muud
  • -
-

-Palun arvesta, et K-9 Mail ei toeta enamusi tasuta Hotmail\'i kontosid ning sarnaselt muude e-posti klientidega -on mõningaid kiikse Microsoft Exchange\'i kasutamisel. -

-Veateated saad saata, kaastööd teha ning küsida teavet järgmisel lehel: -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nSaadetud Androidi seadmelt K-9 meiliga. Vabanda, et nii lühdalt. Konto \"%s\" eemaldatakse K-9 Mailist. diff --git a/app/ui/legacy/src/main/res/values-eu/strings.xml b/app/ui/legacy/src/main/res/values-eu/strings.xml index 12a3028713..021d3049ad 100644 --- a/app/ui/legacy/src/main/res/values-eu/strings.xml +++ b/app/ui/legacy/src/main/res/values-eu/strings.xml @@ -27,38 +27,7 @@ Ikusi zer den berria bertsio honetan - - Ongi etorri K-9 Mail-era - -K-9 Mail Androiderako posta elektroniko bezero libre ahaltsu bat da. -

-Ondorengo eginbide hobetuak ditu: -

-
    -
  • \"Push\" posta IMAP IDLE erabiliz
  • -
  • Errendimendu hobea
  • -
  • Mezu artxibatzea
  • -
  • Posta elektronikoen sinadurak
  • -
  • Bcc-bere-buruari
  • -
  • Harpidetza karpetetara
  • -
  • Karpeta guztien sinkronizazioa
  • -
  • Erantzuteko helbidearen konfigurazioa
  • -
  • Laster-teklak
  • -
  • Bateragarritasun hobea IMAPekin
  • -
  • Eranskinak SD txartelean gordetzea
  • -
  • Hustu Zakarrontzia
  • -
  • Mezuen ordenatzea
  • -
  • …eta gehiago
  • -
-

-Mesedez kontuan hartu K-9 Mail ez dela bateragarria Hotmail-en doako kontu gehienekin eta, posta bezero askok bezala, bitxikeria batzuk ditu Microsoft Exchange-rekin komunikatzerakoan. -

-Mesedez akatsen berri emateko, ezaugarri berriak gehitzeko eta galderak egiteko -https://github.com/k9mail/k-9/ erabili. -

- ]]>
- + -- \nAndroid gailutik bidalia K-9 Mail erabiliz. Barka laburtasuna. \"%s\" kontua K-9 Mail-etik kenduko da. diff --git a/app/ui/legacy/src/main/res/values-fa/strings.xml b/app/ui/legacy/src/main/res/values-fa/strings.xml index bad5f0e6dc..e2c152970f 100644 --- a/app/ui/legacy/src/main/res/values-fa/strings.xml +++ b/app/ui/legacy/src/main/res/values-fa/strings.xml @@ -28,38 +28,7 @@ از تازه‌های این نسخه باخبر شوید نما - - به «K-9 Mail» خوش آمدید - -‏K-9 Mail برنامه‌ای رایگان برای مدیریت رایانامه در اندروید است. -

-برخی از قابلیت‌های بهبودیافتهٔ آن: -

-
    -
  • پیشرانی رایانامه (Push Mail) با استفاده از IMAP IDLE
  • -
  • عملکرد بهتر
  • -
  • سامان‌دهی پیام‌ها
  • -
  • امضاهای رایانامه
  • -
  • ارسال مخفیانه به خود (Bcc-to-self)
  • -
  • اشتراک به پوشه‌های خاص با IMAP
  • -
  • همگام‌سازی همهٔ پوشه‌ها
  • -
  • تنظیماتی برای نشانی «پاسخ به»
  • -
  • میانبرهای صفحه‌کلید
  • -
  • پشتیبانی بهتر از IMAP
  • -
  • ذخیرهٔ پیوست‌ها در کارت SD
  • -
  • خالی‌کردن زباله‌دان
  • -
  • مرتب‌سازی پیام‌ها
  • -
  • و خیلی قابلیت‌های دیگر…
  • -
-

-لطفاً توجه کنید که K-9، مانند بسیاری از برنامه‌های مدیریت رایانامه، از بیشتر حساب‌های رایگان Hotmail پشتیبانی نمی‌کند و هنگام برقراری ارتباط‌ با Microsoft Exchange مشکلاتی وجود دارد. -

-لطفاً گزارش‌های خطا، همکاری برای قابلیت جدید و پرسش‌هایتان را در اینجا مطرح کنید: -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nاز دستگاه اندرویدی‌ام و به‌وسیلهٔ K-9 Mail ارسال شد. حساب «%s» از K-9 Mail حذف خواهد شد. diff --git a/app/ui/legacy/src/main/res/values-fi/strings.xml b/app/ui/legacy/src/main/res/values-fi/strings.xml index 2818bf24d2..e0457e6883 100644 --- a/app/ui/legacy/src/main/res/values-fi/strings.xml +++ b/app/ui/legacy/src/main/res/values-fi/strings.xml @@ -28,38 +28,7 @@ Selvitä mitä uutta tämä julkaisu sisältää Näytä - - Tervetuloa K-9 Mailiin - -K-9 Mail on monipuolinen ilmainen sähköpostisovellus Androidille. -

-Sen ominaisuuksiin kuuluu muun muassa: -

-
    -
  • Push-viestit käyttäen IMAP IDLE -toteutusta
  • -
  • Aiempaa parempi suorituskyky
  • -
  • Viestien arkistointi
  • -
  • Sähköpostin allekirjoitukset
  • -
  • Piilokopioiden lähetys itselle
  • -
  • Kansiotilaukset
  • -
  • Kaikkien kansioiden synkronointi
  • -
  • Vastausosoitteen määritys
  • -
  • Pikanäppäimet
  • -
  • Aiempaa parempi IMAP-tuki
  • -
  • Liitteiden tallennus muistikortille
  • -
  • Roskakorin tyhjennys
  • -
  • Viestien järjestely
  • -
  • …ja paljon muuta
  • -
-

-Huomioithan, että K-9 ei tue useimpia ilmaisia Hotmail-tilejä, ja kuten monet muut sovellukset, saattaa kärsiä pienistä ongelmista Microsoft Exchange -ympäristössä. -

-Ilmoita virheistä, ota osaa sovelluskehitykseen ja esitä kysymyksiä osoitteessa -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nLähetetty Android-laitteestani K-9 Maililla. Pahoittelut vähäsanaisuudestani. Tili \"%s\" poistetaan K-9 Mailista. diff --git a/app/ui/legacy/src/main/res/values-fr/strings.xml b/app/ui/legacy/src/main/res/values-fr/strings.xml index f5ab6c8a51..813bf879ff 100644 --- a/app/ui/legacy/src/main/res/values-fr/strings.xml +++ b/app/ui/legacy/src/main/res/values-fr/strings.xml @@ -28,38 +28,7 @@ Découvrez les nouveautés de cette version Afficher - - Bienvenue sur Courriel K-9 Mail - -Courriel K-9 Mail est un client de courriel puissant et ouvert pour Android. -

-Ses fonctions améliorées incluent : -

-
    -
  • Courriel poussé utilisant IMAP IDLE
  • -
  • Meilleures performances
  • -
  • Réarchivage des courriels
  • -
  • Signatures des courriels
  • -
  • Cci-à-soi
  • -
  • Abonnement aux dossiers
  • -
  • Synchronisation de tous les dossiers
  • -
  • Configuration de l’adresse de retour
  • -
  • Raccourcis-clavier
  • -
  • Meilleure prise en charge IMAP
  • -
  • Enregistrement des fichiers joints sur la carte SD
  • -
  • Vidage de la corbeille
  • -
  • Tri des courriels
  • -
  • et plus…
  • -
-

-Veuillez noter que K-9 ne prend pas en charge la plupart des comptes Hotmail gratuits et que, comme pour beaucoup de clients de courriel, la communication avec Microsoft Exchange est capricieuse. -

-Rapportez les bogues, recommandez de nouvelles fonctions et posez vos questions sur -https://github.com/k9mail/k-9/. -

-]]>
- + -- \nEnvoyé de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma brièveté. Le compte « %s » sera supprimé de Courriel K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-fy/strings.xml b/app/ui/legacy/src/main/res/values-fy/strings.xml index f6909e781d..c295f776b6 100644 --- a/app/ui/legacy/src/main/res/values-fy/strings.xml +++ b/app/ui/legacy/src/main/res/values-fy/strings.xml @@ -28,34 +28,7 @@ Untdek wat der nij is yn dizze ferzje Besjen - - Wolkom by K-9 Mail - K-9 Mail is in fergees krêftige e-mailclient foar Android.

De ferbettere mooglikheden bestean ûnder oare út: -

-
    -
  • Pushmail middels IMAP IDLE
  • -
  • Bettere prestaasjes
  • -
  • Berjocht werklassifikaasje
  • -
  • E-mailhantekeningen
  • -
  • Bcc nei josels
  • -
  • Mapabonneminten
  • -
  • Syngronisaasje fan alle mappen
  • -
  • Antwurdadres ynstelle
  • -
  • Toetseboerd fluchkeppelingen
  • -
  • Bettere stipe IMAP
  • -
  • Bylage bewarje nei SD
  • -
  • Jiskefet leegje
  • -
  • Berjochten sortearje
  • -
  • en mear…
  • -
-

-Hâld der rekkening mei dat K-9 de measte fergeze Hotmail-accounts net stipet, en krekt as in protte e-mailclients, problemen hawwe kin om te ferbinen mei Microsoft Exchange. -

-Graach flaterrapporten stjoere, bydragen foar nije funksjes en fragen stelle op -https://github.com/k9mail/k-9/. -

-]]>
- + -- \nFerstjoerd fan myn Android-apparaat ôf mei K-9 Mail. De account ‘%s’ wurdt út K-9 Mail fuortsmiten. diff --git a/app/ui/legacy/src/main/res/values-gd/strings.xml b/app/ui/legacy/src/main/res/values-gd/strings.xml index 4694ffd1a4..9bf039085c 100644 --- a/app/ui/legacy/src/main/res/values-gd/strings.xml +++ b/app/ui/legacy/src/main/res/values-gd/strings.xml @@ -23,10 +23,7 @@ Na tha ùr - - Fàilte gu aplacaid a’ phuist - <p> Tha aplacaid a’ phuist ’na aplacaid shaor agus chumhachdach airson post-d air Android. </p><p> Tha na gleusan leasaichte aige a’ gabhail a-staigh: </p> <ul> <li>Put post slighe IMAP IDLE</li> <li>Dèanadas nas fheàrr</li> <li>Ath-fhaidhleadh theachdaireachdan</li> <li>Eàrr-sgrìobhaidhean puist-d</li> <li>Bcc dhut fhèin</li> <li>Fo-sgrìobhaidhean phasganan</li> <li>Sioncronachadh nam pasgan air fad</li> <li>Rèiteachadh seòladh nam freagairt</li> <li>Ath-ghoiridean a’ mheur-chlàir</li> <li>Taic nas fheàrr airson IMAP</li> <li>Sàbhaladh de cheanglachain air SD</li> <li>Falamhachadh an sgudail</li> <li>Seòrsachadh theachdaireachdan</li> <li>…is mòran a bharrachd</li> </ul> <p> Thoir an aire nach cuir aplacaid a’ phuist taic ri cuid mhòr de chunntasan saora Hotmail agus mar iomadh prògram puist-d eile, tachraidh rudan neònach nuair a bhruidhneas e ri Microsoft Exchange. </p><p> Fàilte air bugaichean, com-pàirteachas, iarrtasan airson gleusan ùra is ceistean aig <a href=https://github.com/k9mail/k-9/>https://github.com/k9mail/k-9/</a>. </p> - + -- Chaidh a chur le post /e/. Thèid an cunntas “%s” a thoirt air falbh on phost. diff --git a/app/ui/legacy/src/main/res/values-gl/strings.xml b/app/ui/legacy/src/main/res/values-gl/strings.xml index fb388f6c67..1dabc2a174 100644 --- a/app/ui/legacy/src/main/res/values-gl/strings.xml +++ b/app/ui/legacy/src/main/res/values-gl/strings.xml @@ -25,39 +25,7 @@ Mira as novidades deste lanzamento - - Benvido/a a K-9 Mail - -K-9 Mail é un potente cliente de correo para Android. -

-As características melloradas inclúen: -

-
    -
  • Push mail utilizando IMAP IDLE
  • -
  • Mellor rendemento
  • -
  • Autocompletado de mensaxe
  • -
  • Firmas de correo
  • -
  • Bcc ao remitente
  • -
  • Suscrición de cartafoles
  • -
  • Sincronización de todos os cartafoles
  • -
  • Configuración da conta de resposta
  • -
  • Atallos de teclado
  • -
  • Melloras no xestión IMAP
  • -
  • Gardar anexos en tarxeta SD
  • -
  • Baldeirar o lixo
  • -
  • Ordenar mensaxes
  • -
  • …e máis
  • -
-

-Por favor teña en conta que K-9 non soporta a maioría das contas gratuítas Hotmail e, como moitos clientes, ten -problemiñas ao utilizar Microsoft Exchange. -

-Por favor envíen informes de fallos, contribúa con novas características e consulte dúbidas en -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nEnviado dende o meu teléfono Android con K-9 Mail. Desculpa a miña brevedade A conta \"%s\" será eliminada de K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-hr/strings.xml b/app/ui/legacy/src/main/res/values-hr/strings.xml index bb51fee3ac..7eb496c9ba 100644 --- a/app/ui/legacy/src/main/res/values-hr/strings.xml +++ b/app/ui/legacy/src/main/res/values-hr/strings.xml @@ -13,8 +13,6 @@ Licenca - - Dobrodošli u K-9 Mail -- \nPoslano sa mog Android uređaja sa K-9 Mail. Molim vas oprostite na mojoj sažetosti. diff --git a/app/ui/legacy/src/main/res/values-hu/strings.xml b/app/ui/legacy/src/main/res/values-hu/strings.xml index a6b27f5785..e43608b297 100644 --- a/app/ui/legacy/src/main/res/values-hu/strings.xml +++ b/app/ui/legacy/src/main/res/values-hu/strings.xml @@ -28,37 +28,7 @@ Tudja meg, hogy mik az újdonságok ebben a kiadásban Megtekintés - - Üdvözli a K-9 Mail - -A K-9 Mail egy hatékony, ingyenes e-mail alkalmazás Androidra. -

-Továbbfejlesztett funkciók: -

-
    -
  • E-mail küldés IMAP IDLE segítségével
  • -
  • Jobb működés
  • -
  • Üzenet iktatás
  • -
  • E-mail aláírások
  • -
  • Titkos másolat saját részre
  • -
  • Mappa váltogatások
  • -
  • Összes mappa szinkronizálása
  • -
  • Visszatérési cím konfiguráció
  • -
  • Gyorsbillentyűk
  • -
  • Jobb IMAP-támogatás
  • -
  • Mellékletek mentése SD-kártyára
  • -
  • Lomtár ürítése
  • -
  • Üzenetek rendezése
  • -
  • …és egyebek
  • -
-

A K-9 nem támogatja a legtöbb Hotmail-fiókot, és sok e-mail alkalmazáshoz hasonlóan, vannak furcsaságok a Microsoft Exchange kezelésében. -

-Hibajelentések beküldésével közreműködhet az új funkciókban, és kérdéseket tehet fel a -https://github.com/k9mail/k-9/ webcímen. -

- ]]>
- + -- \nAndroidos készülékről küldve K-9 Mail használatával. Elnézést a rövidségért. A(z) „%s” fiók eltávolításra kerül a K-9 Mail alkalmazásból. diff --git a/app/ui/legacy/src/main/res/values-in/strings.xml b/app/ui/legacy/src/main/res/values-in/strings.xml index 1a28e41c96..116acc70e7 100644 --- a/app/ui/legacy/src/main/res/values-in/strings.xml +++ b/app/ui/legacy/src/main/res/values-in/strings.xml @@ -25,38 +25,7 @@ Apa yang baru - - Selamat datang di K-9 Mail - -K-9 Mail adalah klien email gratis yang hebat untuk Android. -

-Fitur yang disempurnakan meliputi: -

-
    -
  • Push mail menggunakan IMAP IDLE
  • -
  • Kinerja yang lebih baik
  • -
  • Penyempurnaan pesan
  • -
  • Tanda tangan email
  • -
  • Bcc-untuk-diri
  • -
  • Langganan folder
  • -
  • Semua sinkronisasi folder
  • -
  • Konfigurasi alamat kembali
  • -
  • Pintasan keyboard
  • -
  • Dukungan IMAP lebih baik
  • -
  • Menyimpan lampiran ke SD
  • -
  • Sampah kosong
  • -
  • Penyortiran pesan
  • -
  • … dan banyak lagi
  • -
-

-Harap dicatat bahwa K-9 tidak mendukung sebagian besar akun Hotmail gratis dan, seperti banyak klien email lainnya -beberapa kebiasaan saat berbicara dengan Microsoft Exchange. -

-Kirimkan laporan bug, kontribusikan fitur baru dan ajukan pertanyaan di -https:/github.com/k9mail/k-9/.

-]]>
- + -- \nDikirim dari perangkat Android saya menggunakan K-9 Mail. Akun \"%s\" akan dibuang dari K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-is/strings.xml b/app/ui/legacy/src/main/res/values-is/strings.xml index dd2c9eac7f..ea764e065d 100644 --- a/app/ui/legacy/src/main/res/values-is/strings.xml +++ b/app/ui/legacy/src/main/res/values-is/strings.xml @@ -28,38 +28,7 @@ Skoðaðu hvað sé nýtt við þessa útgáfu Skoða - - Velkomin í K-9 póstinn - -K-9 Mail er öflugt, frjálst tölvupóstforrit fyrir Android. -

-Meðal bættra eiginleika þess eru: -

-
    -
  • Ýtipóstur með IMAP IDLE
  • -
  • Betri afköst
  • -
  • Endurflokkun skilaboða
  • -
  • Meðhöndlun undirskrifta
  • -
  • Bcc-til-sjálfs
  • -
  • Áskriftir að möppum
  • -
  • Samstilling allra mappa
  • -
  • Uppsetning svarpóstfangs
  • -
  • Flýtilyklar
  • -
  • Betri IMAP-stuðningur
  • -
  • Vistun viðhengja á SD
  • -
  • Tæming á rusli
  • -
  • Röðun skilaboða
  • -
  • …og margt fleira
  • -
-

-Taktu eftir því að K-9 gengur ekki með flestum Hotmail aðgöngum og, rétt eins og mörg önnur tölvupóstforrit, á í nokkrum erfiðleikum með að hafa samskipti við Microsoft Exchange. -

-Sendu inn villuskýrslur, leggðu fram nýja eiginleika og spurðu spurninga á -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nSent úr Android tækinu mínu með K-9 póstforritinu. Afsakaðu hvað ég stytti mál mitt mikið. Aðgangurinn \"%s\" verður fjarlægður úr K-9 póstinum. diff --git a/app/ui/legacy/src/main/res/values-it/strings.xml b/app/ui/legacy/src/main/res/values-it/strings.xml index a60ab4bae3..5c7a6ecaa2 100644 --- a/app/ui/legacy/src/main/res/values-it/strings.xml +++ b/app/ui/legacy/src/main/res/values-it/strings.xml @@ -28,39 +28,7 @@ Scopri le novità di questa versione Vedi - - Benvenuto in K-9 Mail - -K-9 Mail è un potente client di posta libero e gratuito per Android. -

-Le sue funzioni migliorate includono: -

-
    -
  • Ricezione email push utilizzando IMAP IDLE
  • -
  • Migliori prestazioni
  • -
  • Ri-archiviazione dei messaggi
  • -
  • Firme dei messaggi
  • -
  • Auto CCN
  • -
  • Sottoscrizioni delle cartelle
  • -
  • Sincronizzazione di tutte le cartelle
  • -
  • Configurazione dell\'indirizzo di risposta
  • -
  • Scorciatoie da tastiera
  • -
  • Migliore supporto IMAP
  • -
  • Salvataggio degli allegati su SD
  • -
  • Svuotamento cestino
  • -
  • Ordinamento dei messaggi
  • -
  • …e altro
  • -
-

-Nota che K-9 non supporta la maggior parte degli account gratuiti Hotmail e, come molti altri client di posta, ha -qualche problema quando dialoga con Microsoft Exchange. -

-Invia segnalazioni di bug, contribuisci con nuove funzionalità e poni domande su -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nInviato dal mio dispositivo Android con K-9 Mail. Perdonate la brevità. L\'account \"%s\" sarà rimosso da K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-iw/strings.xml b/app/ui/legacy/src/main/res/values-iw/strings.xml index 329c608300..c925655ec3 100644 --- a/app/ui/legacy/src/main/res/values-iw/strings.xml +++ b/app/ui/legacy/src/main/res/values-iw/strings.xml @@ -20,9 +20,7 @@ גלה מה חדש בגירסא זו - - ברוך הבא אל דואר K-9 - + -- \nנשלח ממכשיר האנדרואיד שלי בעזרת אפליקציית הדואר K-9. סלח לי על הקצרנות. החשבון \"%s\" יימחק מדואר K-9 . diff --git a/app/ui/legacy/src/main/res/values-ja/strings.xml b/app/ui/legacy/src/main/res/values-ja/strings.xml index f2c2ed28d4..b672816abc 100644 --- a/app/ui/legacy/src/main/res/values-ja/strings.xml +++ b/app/ui/legacy/src/main/res/values-ja/strings.xml @@ -28,39 +28,7 @@ このリリースは何が新しいのかを知る 表示 - - K-9 Mailへようこそ - -K-9 Mail は Android 向けの強力なフリーのメールクライアントです。 -

-改良された機能: -

-
    -
  • IMAP IDLE を利用したプッシュメール
  • -
  • パフォーマンス改善
  • -
  • メッセージ整理
  • -
  • 電子メール署名
  • -
  • Bcc-to-self
  • -
  • フォルダ購読
  • -
  • 全フォルダ同期
  • -
  • 返信先の設定
  • -
  • キーボードショートカット
  • -
  • IMAP サポート改善
  • -
  • 添付ファイルをSDカードに保存
  • -
  • ゴミ箱を空にする機能
  • -
  • メッセージのソート
  • -
  • …他にもたくさんあります
  • -
-

-K-9 は大多数のメールクライアントと同様に、ほとんどのフリー Hotmail アカウントをサポートしていません。 -また、 Microsoft Exchange との通信において少し癖があることに注意してください。 -

-バグレポートや新機能の貢献、質問は https://github.com/k9mail/k-9/ にお願いします。 -日本語で質問などがある場合は https://groups.google.co.jp/group/k9mail_ja/ を参照してください。 -

-]]>
- + -- \nK-9 Mail で Android デバイスから送信しました。簡単で申し訳ありません。 アカウント \"%s\" はK-9 Mailから削除されます。 diff --git a/app/ui/legacy/src/main/res/values-ko/strings.xml b/app/ui/legacy/src/main/res/values-ko/strings.xml index 764ff07dfc..7e1317b059 100644 --- a/app/ui/legacy/src/main/res/values-ko/strings.xml +++ b/app/ui/legacy/src/main/res/values-ko/strings.xml @@ -26,8 +26,6 @@ 이 릴리즈의 새로운 기능 알아보기 - - K-9 메일을 사용하시게 된 것을 환영합니다 -- \n안드로이드 기기에서 K-9 메일을 사용해 보낸 메일입니다. diff --git a/app/ui/legacy/src/main/res/values-lt/strings.xml b/app/ui/legacy/src/main/res/values-lt/strings.xml index 61d5cd8603..66f2fe1963 100644 --- a/app/ui/legacy/src/main/res/values-lt/strings.xml +++ b/app/ui/legacy/src/main/res/values-lt/strings.xml @@ -27,39 +27,7 @@ Sužinokite, kas naujo šioje versijoje - - Sveiki atvykę į K-9 paštą - -K-9 Paštas yra galingas nemokamas Android el. pašto klientas. -

-Patobulintos šios funkcijos: -

-
    -
  • Push laiškai naudojant IMAP IDLE
  • -
  • Geresnis našumas
  • -
  • Laiško pildymas iš naujo
  • -
  • Laiškų parašai
  • -
  • Bcc-sau
  • -
  • Aplankų prenumeratos
  • -
  • Visų aplankų sinchronizacija
  • -
  • Atgalinio adreso konfigūracija
  • -
  • Spartieji klaviatūros klavišai
  • -
  • Geresnis IMAP palaikymas
  • -
  • Priedų įrašymas į SD
  • -
  • Šiukšlinės tuštinimas
  • -
  • Laiškų rūšiavimas
  • -
  • …ir daugiau
  • -
-

-Atkreipkite dėmesį, kad K-9 nepalaiko daugumos nemokamų Hotmail paskyrų ir, kaip ir daugelis pašto klientų, turi -kai kurių keistenybių bendraujant su Microsoft Exchange. -

-Pateikite pranešimus apie klaidas, prisidėkite prie naujų funkcijų kūrimo ir užduokite klausimus adresu -https://github.com/k9mail/k-9/. -

- ]]>
- + - \nIšsiųsta iš mano Android įrenginio naudojant K-9 Mail. Atleiskite už trumpumą. Paskyra \"%s\" bus pašalinta iš „K-9 Mail“. diff --git a/app/ui/legacy/src/main/res/values-lv/strings.xml b/app/ui/legacy/src/main/res/values-lv/strings.xml index b43ddac748..acec7983a5 100644 --- a/app/ui/legacy/src/main/res/values-lv/strings.xml +++ b/app/ui/legacy/src/main/res/values-lv/strings.xml @@ -28,38 +28,7 @@ Uzzināt, kas jauns šajā versijā Skatīt - - Laipni lūdzam K-9 Pastā - -K-9 Mail ir spēcīga bezmaksas e-pasta programma Android operētājsistēmai. -

-Tās uzlaboto iespēju skaitā ir: -

-
    -
  • Pasta lejupielādēšana, izmantojot IMAP IDLE
  • -
  • Labāka veiktspēja
  • -
  • Vēstuļu arhivēšana
  • -
  • E-pasta paraksti
  • -
  • Bcc-pašam sev
  • -
  • Pieteikšanās mapēm
  • -
  • Visu mapju sinhronizēšana
  • -
  • Atpakaļsūtīšanas adreses iestatīšana
  • -
  • Tastatūras īsceļi
  • -
  • Labāks IMAP atbalsts
  • -
  • Pielikumu saglabāšana uz SD kartes
  • -
  • Miskastes iztukšošana
  • -
  • Vēstuļu kārtošana
  • -
  • …un daudz kas cits
  • -
-

-Lūdzu, ņemiet vērā, kā K-9 neatbalsta lielāko daļu bezmaksas Hotmail kontu, un tāpat kā daudzām citām e-pasta programmām tai mēdz būt problēmas ar Microsoft Exchange. -

-Lūdzu, iesniedziet kļūdu ziņojumus, ierosiniet jaunas iespējas un uzdodiet jautājumus -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nNosūtīts ar K-9 Pastu no manas Android ierīces. Atvainojiet, ka esmu tik kodolīgs. Konts \"%s\" tiks noņemts no K-9 Pasta. diff --git a/app/ui/legacy/src/main/res/values-ml/strings.xml b/app/ui/legacy/src/main/res/values-ml/strings.xml index d769f91ba5..9d9a2398cc 100644 --- a/app/ui/legacy/src/main/res/values-ml/strings.xml +++ b/app/ui/legacy/src/main/res/values-ml/strings.xml @@ -25,38 +25,7 @@ ഈ റിലീസിൽ പുതിയത് എന്താണെന്ന് കണ്ടെത്തുക - - കെ-9 മെയിലിലേക്ക് സ്വാഗതം - -കെ-9 മെയിൽ എന്നത് ആൻഡ്രോയിഡിനായുള്ള ഒരു സൗജന്യവും ശക്തവുമായ ഇ-മെയിൽ ക്ലയന്റ് ആണ്. -

-ഇതിന്റെ മെച്ചപ്പെടുത്തിയ സവിശേഷതകളിൽ ഇവ ഉൾപ്പെടുന്നു: -

-
    -
  • IMAP IDLE ഉപയോഗിച്ച് മെയിൽ പുഷ് ചെയ്യുക
  • -
  • മികച്ച പ്രകടനം
  • -
  • സന്ദേശം വീണ്ടും നിറയ്ക്കുന്നു
  • -
  • ഇ-മെയിൽ ഒപ്പുകൾ
  • -
  • Bcc-to-self
  • -
  • ഫോൾഡർ സബ്‌സ്‌ക്രിപ്‌ഷനുകൾ
  • -
  • സംയുക്ത ഫോൾഡർ സമന്വയം
  • -
  • റിട്ടേൺ-അഡ്രസ് കോൺഫിഗറേഷൻ
  • -
  • കീബോർഡ് കുറുക്കുവഴികൾ
  • -
  • മികച്ച IMAP പിന്തുണ
  • -
  • SD-ലേക്ക് അറ്റാച്ചുമെന്റുകൾ സംരക്ഷിക്കുന്നു
  • -
  • ചവറ്റുകുട്ട ശൂന്യമാക്കൽ
  • -
  • സന്ദേശം തരംതിരിക്കൽ
  • -
  • …കൂടാതെ വേറെയും
  • -
-

-മിക്ക സൗജന്യ ഹോട്ട്‌മെയിൽ അക്കൗണ്ടുകളെയും കെ-9 പിന്തുണയ്ക്കുന്നില്ലെന്നും മൈക്രോസോഫ്റ്റ് എക്സ്ചേഞ്ചുമായി ബന്ധപ്പെടുമ്പോൾ പല ഇമെയിൽ ക്ലയന്റുകളെയും പോലെ ചില ബുദ്ധിമുട്ടുകളുണ്ടെന്നും ദയവായി ശ്രദ്ധിക്കുക. -

-ബഗ് റിപ്പോർട്ടുകൾ സമർപ്പിക്കുക, പുതിയ സവിശേഷതകൾ സംഭാവന ചെയ്യുക, കൂടാതെ ചോദ്യങ്ങൾ ചോദിക്കുക -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nകെ-9 മെയിൽ ഉപയോഗിച്ച് എന്റെ ആൻഡ്രോയിഡിൽ നിന്നും അയച്ചത്. ദയവായി എന്റെ പദപ്രയോഗമിതത്വം ക്ഷമിക്കുക. കെ-9 മെയിലിൽ നിന്ന് \"%s\" അക്കൗണ്ട് നീക്കംചെയ്യും. diff --git a/app/ui/legacy/src/main/res/values-nb/strings.xml b/app/ui/legacy/src/main/res/values-nb/strings.xml index 3fdf1b871a..0210019d67 100644 --- a/app/ui/legacy/src/main/res/values-nb/strings.xml +++ b/app/ui/legacy/src/main/res/values-nb/strings.xml @@ -20,39 +20,7 @@ Hva er nytt? - - Velkommen til K-9 e-post - -K-9 E-post er en kraftig og fri e-postklient for Android. -

-Dets forbedrede funksjoner inkluderer: -

-
    -
  • Push-mail ved bruk av IMAP IDLE
  • -
  • Bedre ytelse
  • -
  • Rearkivering av meldinger
  • -
  • E-postsignaturer
  • -
  • Blindkopi ti deg selv
  • -
  • Mappeabonnement
  • -
  • Synkronisering av alle mapper
  • -
  • Returadressekonfigurasjon
  • -
  • Tastatursnarveier
  • -
  • Bedre IMAP-støtte
  • -
  • Lagre vedlegg til SD-kort
  • -
  • Tøm søppel
  • -
  • Meldingssortering
  • -
  • …med mer
  • -
-

-Merk at K-9 ikke støtter de fleste gratis Hotmail-kontoer, og har, som mange andre -e-postklienter, noen problemer med å snakke med Microsoft Exchange. -

-Send feilmeldinger, bidra med nye funksjoner og still spørsmål her: -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nSendt fra min Android-enhet med K-9 e-post. Unnskyld min kortfattethet. Kontoen \"%s\" vil bli fjernet fra K-9 e-post diff --git a/app/ui/legacy/src/main/res/values-nl/strings.xml b/app/ui/legacy/src/main/res/values-nl/strings.xml index 9891d6127b..5afc5fce04 100644 --- a/app/ui/legacy/src/main/res/values-nl/strings.xml +++ b/app/ui/legacy/src/main/res/values-nl/strings.xml @@ -28,34 +28,7 @@ Ontdek wat er nieuw is in deze versie Bekijken - - Welkom bij K-9 Mail - K-9 Mail is een gratis krachtige e-mailclient voor Android.

De verbeterde mogelijkheden bestaan ondermeer uit: -

-
    -
  • Pushmail middels IMAP IDLE
  • -
  • Betere prestaties
  • -
  • Berichtherclassificatie
  • -
  • E-mailhandtekeningen
  • -
  • Bcc naar jezelf
  • -
  • Mapabonnementen
  • -
  • Synchronisatie van alle mappen
  • -
  • Antwoordadres instellen
  • -
  • Toetsenbordsnelkoppelingen
  • -
  • Betere IMAP-ondersteuning
  • -
  • Bijlage opslaan naar SD
  • -
  • Prullenbak legen
  • -
  • Berichten sorteren
  • -
  • en meer…
  • -
-

-Houd er rekening mee dat K-9 de meeste gratis Hotmail-accounts niet ondersteund, en net als veel e-mailclients, problemen kan hebben om te verbinden met Microsoft Exchange. -

-Graag foutrapporten sturen, bijdragen voor nieuwe functies en vragen stellen op -https://github.com/k9mail/k-9/. -

-]]>
- + -- \nVerstuurd vanaf mijn Android-apparaat met K-9 Mail. De account ‘%s’ wordt uit K-9 Mail verwijderd. diff --git a/app/ui/legacy/src/main/res/values-pl/strings.xml b/app/ui/legacy/src/main/res/values-pl/strings.xml index 22b3886914..b7a9fcc655 100644 --- a/app/ui/legacy/src/main/res/values-pl/strings.xml +++ b/app/ui/legacy/src/main/res/values-pl/strings.xml @@ -28,38 +28,7 @@ Dowiedz się, co nowego w tej wersji Wyświetl - - Witaj w K-9 Mail - -K-9 Mail to darmowy zaawansowany program pocztowy dla systemu Android. -

-Oto niektóre z jego istotnych funkcji: -

-
    -
  • Obsługa Push mail z użyciem IMAP IDLE
  • -
  • Lepsza wydajność
  • -
  • Reorganizowanie wiadomości
  • -
  • Podpisy wiadomości e-mail
  • -
  • Kopia UDW-do-siebie
  • -
  • Subskrybowanie folderów
  • -
  • Synchronizowanie wszystkich folderów
  • -
  • Konfigurowanie adresu zwrotnego
  • -
  • Skróty klawiszowe
  • -
  • Lepsza obsługa protokołu IMAP
  • -
  • Zapisywanie załączników na karcie SD
  • -
  • Opróżnianie kosza
  • -
  • Sortowanie wiadomości
  • -
  • …i wiele innych
  • -
-

-K-9 nie obsługuje większości darmowych kont Hotmail oraz, jak wiele innych programów pocztowych, może być kapryśny przy połączeniach z serwerami Microsoft Exchange. -

-Wszelkie zgłoszenia usterek, zapytania oraz pomysły na nowe funkcje prosimy przesyłać za pośrednictwem strony projektu -https://github.com/k9mail/k-9/. -

- ]]>
- + -- Wysłane z urządzenia Android za pomocą K-9 Mail. Proszę wybaczyć moją zwięzłość. diff --git a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml index 00283726ff..c1ebb3f3bd 100644 --- a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml +++ b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml @@ -28,38 +28,7 @@ Descubra as novidades dessa versão Ver - - Bem-vindo ao K-9 Mail - -K-9 Mail é um poderoso cliente de e-mails gratuito para Android. -

-Suas funcionalidades incluem: -

-
    -
  • Sincronização de e-mail usando IMAP IDLE
  • -
  • Performance aprimorada
  • -
  • Realocação de mensagens
  • -
  • Assinatura de e-mails
  • -
  • Cópia oculta para si mesmo
  • -
  • Assinatura de pastas
  • -
  • Sincronização completa de pastas
  • -
  • Configuração de endereço de retorno
  • -
  • Atalhos de teclado
  • -
  • Suporte aprimorado ao IMAP
  • -
  • Salvamento de anexos para o cartão SD
  • -
  • Esvaziamento de lixeira
  • -
  • Ordenação de mensagens
  • -
  • … e mais
  • -
-

-Saiba que o K-9 não suporta a maioria das contas gratuitas de Hotmail e, assim como vários outros clientes de e-mail, tem alguns problemas ao conversar com o Microsoft Exchange. -

-Por favor encaminhe relatórios de bugs, contribua com novos recursos e tire dúvidas no -https://github.com/k9mail/k-9/. -

-]]>
- + -- \nEnviado de meu dispositivo Android com K-9 mail. Desculpe-me pela brevidade. A conta \"%s\" será removida do K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml index 213db22f8c..90aa9ae511 100644 --- a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml +++ b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml @@ -28,39 +28,7 @@ Descubra o que há de novo nesta versão Ver - - Bem-vindo ao K-9 Mail - -O K-9 Mail é um poderoso cliente de email grátis para o Android. -

-As suas funcionalidades melhoradas incluem: -

-
    -
  • Push de email usando IMAP IDLE
  • -
  • Melhor performance
  • -
  • Relocação de mensagens
  • -
  • Assinaturas de email
  • -
  • Bcc para o próprio
  • -
  • Subscrição de pastas
  • -
  • Sincronização de todas as pastas
  • -
  • Configuração de endereço de retorno
  • -
  • Atalhos de teclado
  • -
  • Melhor suporte IMAP
  • -
  • Guardar anexos para o cartão SD
  • -
  • Esvaziar lixo
  • -
  • Ordenação de mensagens
  • -
  • …e mais
  • -
-

-Por favor note que o K-9 não suporta a maioria das contas gratuitas do Hotmail e, como muitos clientes de email -tem alguns problemas ao comunicar com o Microsoft Exchange. -

-Por favor envie relatórios de falhas, contribua com novas funcionalidades e coloque as suas dúvidas em -https://github.com/k9mail/k-9/. -

-]]>
- + -- \nEnviado a partir do meu dispositivo Android com o K-9 Mail. Peço desculpa pela brevidade. A conta \"%s\" será removida do K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-ro/strings.xml b/app/ui/legacy/src/main/res/values-ro/strings.xml index 046c1038ab..6abddbd7df 100644 --- a/app/ui/legacy/src/main/res/values-ro/strings.xml +++ b/app/ui/legacy/src/main/res/values-ro/strings.xml @@ -27,38 +27,7 @@ Aflați ce este nou în această versiune - - Bun venit la K-9 Mail - -K-9 Mail este un client puternic și gratuit de email pentru Android. -

-Facilitățile sale îmbunătățite includ: -

-
    -
  • Push mail folosind IMAP IDLE
  • -
  • Performanță mai bună
  • -
  • Reciclare mesaje
  • -
  • Semnături email
  • -
  • Bcc-către-sine
  • -
  • Abonare dosare
  • -
  • Sincronizarea tuturor dosarelor
  • -
  • Adrese de răspuns configurabile
  • -
  • Scurtături tastatură
  • -
  • Suport IMAP mai bun
  • -
  • Salvare atașamente pe cardul SD
  • -
  • Golire Coș de gunoi
  • -
  • Sortare mesaje
  • -
  • …și multe altele
  • -
-

-Rețineți, K-9 nu oferă suport pentru mare parte din conturile gratuite de Hotmail și, precum alți clienți de email, poate avea dificultăți cînd se conectează la Microsoft Exchange. -

-Vă rugăm să ne raportați defecte, să contribuiți cu funcționalități noi sau să puneți întrebări la -https://github.com/k9mail/k-9/. -

-]]>
- + -- \nTrimis de pe dispozitivul meu Android cu K-9 Mail. Rog scuzați mesajul scurt. Contul \"%s\" va fi șters din K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-ru/strings.xml b/app/ui/legacy/src/main/res/values-ru/strings.xml index 7ad655b5bd..debdc15a83 100644 --- a/app/ui/legacy/src/main/res/values-ru/strings.xml +++ b/app/ui/legacy/src/main/res/values-ru/strings.xml @@ -28,38 +28,7 @@ Узнайте, что нового в этом выпуске Показать - - Добро пожаловать! - -K-9 Mail — почтовик для Android. -

-Возможности: -

-
    -
  • всплывающие уведомления,
  • -
  • быстрая работа,
  • -
  • перемещение сообщений,
  • -
  • несколько подписей,
  • -
  • скрытая копия себе,
  • -
  • подписка на папки,
  • -
  • синхронизация всех папок,
  • -
  • адрес для ответа,
  • -
  • горячие клавиши,
  • -
  • улучшенная поддержка IMAP,
  • -
  • сохранение вложений,
  • -
  • очистка корзины,
  • -
  • упорядочивание сообщений,
  • -
  • …и многие другие!
  • -
-

-Пожалуйста, обратите внимание, что K-9 Mail не поддерживает большинство бесплатных учётных записей Hotmail также, как и большинство почтовиков, и имеет некоторые ограничения при работе с MS Exchange . -

-Вопросы, сообщения об ошибках и участие в разработке: -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nПростите за краткость, создано в K-9 Mail. Учётная запись «%s» будет удалена из приложения K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-sk/strings.xml b/app/ui/legacy/src/main/res/values-sk/strings.xml index 78c865ef0b..b86f8dd65c 100644 --- a/app/ui/legacy/src/main/res/values-sk/strings.xml +++ b/app/ui/legacy/src/main/res/values-sk/strings.xml @@ -22,39 +22,7 @@ Verzia %s - - Vitajte v K-9 Mail - -K-9 Mail je výkonný a slobodný e-mailový klient pre Android. -

-Medzi jeho vylepšené funkcie patria: -

-
    -
  • Push pošta pri použití IMAP IDLE
  • -
  • Lepší výkon
  • -
  • Doplňovanie správ
  • -
  • Podpisy správ
  • -
  • Skrytá kópia sebe
  • -
  • Odbery priečinkov
  • -
  • Synchronizácia všetkých priečinkov
  • -
  • Nastavenie spiatočnej adresy
  • -
  • Klávesové skratky
  • -
  • Lepšia podpora IMAP protokolu
  • -
  • Ukladanie príloh na SD kartu
  • -
  • Vyprázdňovanie koša
  • -
  • Zoraďovanie správ
  • -
  • …a ďalšie
  • -
-

-Prosím, vezmite na vedomie, že K-9 Mail nepodporuje väčšinu bezplatných účtov služby Hotmail a ako mnoho ďalších e-mailových klientov -vykazuje isté zvláštnosti pri komunikácii s Microsoft Exchange. -

-Prosím, nahlasujte prípadné chyby, prispievajte novými funkciami a pýtajte sa na -https://github.com/k9mail/k-9/. -

-]]>
- + -- \nOdoslané z môjho Android zariadenia prostredníctvom K-9 Mail. Prosím, ospravedlňte moju stručnosť. Účet \"%s\" bude odstránený z K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-sl/strings.xml b/app/ui/legacy/src/main/res/values-sl/strings.xml index bae7cc9236..3a2a05e0de 100644 --- a/app/ui/legacy/src/main/res/values-sl/strings.xml +++ b/app/ui/legacy/src/main/res/values-sl/strings.xml @@ -27,38 +27,7 @@ Kaj je novega v tej izdaji - - Dobrodošli v K-9 Mail - -K-9 Mail je zmogljiv brezplačni odjemalec elektronske pošte za okolje Android. -

-Podpira različne storitve, kot so: -

-
    -
  • potisno pošiljanje pošte z uporabo IMAP IDLE
  • -
  • hitro in odzivno delovanje
  • -
  • prerazporejanje sporočil
  • -
  • podpora različnim podpisom sporočila
  • -
  • slepa povratnica poslanega sporočila
  • -
  • prilagajanje prikazovanja map
  • -
  • izbirno usklajevanje
  • -
  • nastavljanje poljubnega povratnega naslova
  • -
  • tipkovne bližnjice
  • -
  • izboljšana podpora protokolu IMAP
  • -
  • podpora shranjevanja prilog na kartico SD
  • -
  • prilagojeno praznjenje smeti
  • -
  • različne možnosti razvrščanja sporočil
  • -
  • … in še mnogo več.
  • -
-

-Program K-9 Mail ne podpira brezplačnih računov Hotmail in ima (kot tudi mnogo drugih odjemalcev) nekaj težav s podporo Microsoft Exchange. -

-Poročila o napakah, predloge za nove funkcije in vprašanja lahko pošljete na -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nPoslano s programom K-9 Mail. Račun »%s« bo odstranjen iz programa. diff --git a/app/ui/legacy/src/main/res/values-sq/strings.xml b/app/ui/legacy/src/main/res/values-sq/strings.xml index 5604c3c311..38a052ce1c 100644 --- a/app/ui/legacy/src/main/res/values-sq/strings.xml +++ b/app/ui/legacy/src/main/res/values-sq/strings.xml @@ -28,39 +28,7 @@ Mësoni ç\’ka të re në këtë hedhje në qarkullim Shiheni - - Mirë se vini te K-9 Mail - -K-9 Mail është një klient email-esh i lirë, për Android. -

-Në veçoritë e tij të përmirësuara përfshihen: -

-
    -
  • Dërgim push duke përdorur IMAP IDLE
  • -
  • Punim më i mirë
  • -
  • Riskedarizim mesazhesh
  • -
  • Nënshkrime email-esh
  • -
  • Bcc-për vetveten
  • -
  • Pajtime në dosje
  • -
  • Njëkohësim për krejt dosjet
  • -
  • Formësim adrese për kthime
  • -
  • Shkurtore tastiere
  • -
  • Mbulim më të mirë të IMAP-it
  • -
  • Ruajtje bashkëngjitjesh në SD
  • -
  • Zbrazje Hedhurinash
  • -
  • Renditje mesazhesh
  • -
  • …dhe të tjera
  • -
-

-Ju lutemi, mbani parasysh që K-9 nuk mbulon shumicën e llogarive falas Hotmail dhe, ashtu si mjaft klientë email-i, ka disa yçkla -kur komunikon me një shërbyes Microsoft Exchange. -

-Ju lutemi, parashtrim njoftimesh për të meta, kontribute për veçori të reaj dhe pyetjet bëjini te -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nDërguar nga pajisja ime Android, me K-9 Mail. Ju lutem, më ndjeni për shkurtësinë. Llogaria \“%s\” do të hiqet që nga K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-sr/strings.xml b/app/ui/legacy/src/main/res/values-sr/strings.xml index 5e324d40ee..eae894f488 100644 --- a/app/ui/legacy/src/main/res/values-sr/strings.xml +++ b/app/ui/legacy/src/main/res/values-sr/strings.xml @@ -22,38 +22,7 @@ Верзија %s - - Добро дошли у К-9 Пошту - -К-9 Пошта је моћан слободни клијент е-поште за Андроид. -

-Побољшане могућности укључују: -

-
    -
  • Прослеђивање поште користећи IMAP IDLE
  • -
  • Боље преформансе
  • -
  • Реархивисање порука
  • -
  • Потписи е-порука
  • -
  • Бцц себи
  • -
  • Претплате на фасцикле
  • -
  • Синхронизација свих фасцикли
  • -
  • Подешавање повратне адресе
  • -
  • Пречице тастатуре
  • -
  • Боља подршка за IMAP
  • -
  • Упис прилога на СД картицу
  • -
  • Пражњење отпада
  • -
  • Ређање порука
  • -
  • …и још тога
  • -
-

-Имајте на уму да К-9 не подржава већину бесплатних Хотмејл налога и, као и многи клијенти, има проблема при контакту са Мајкрософтовом Разменом. -

-Пријављујте грешке, доприносите нове могућности и постављајте питања на -https://github.com/k9mail/k-9/. -

-]]>
- + -- \nПослато К-9 Поштом са мог Андроид уређаја. Извините због сажетости. Налог „%s“ ће бити уклоњен из К-9 Поште. diff --git a/app/ui/legacy/src/main/res/values-sv/strings.xml b/app/ui/legacy/src/main/res/values-sv/strings.xml index ddc9edbdec..1ce3aaec98 100644 --- a/app/ui/legacy/src/main/res/values-sv/strings.xml +++ b/app/ui/legacy/src/main/res/values-sv/strings.xml @@ -28,38 +28,7 @@ Ta reda på vad som är nytt i denna utgåva Visa - - Välkommen till K-9 Mail - -K-9 Mail är en kraftfull fri e-postklient för Android. -

-Några av funktionerna som förbättrats är: -

-
    -
  • Push-e-post med IMAP IDLE
  • -
  • Bättre prestanda
  • -
  • Meddelandelagring
  • -
  • E-postsignaturer
  • -
  • Blindkopia-till-dig-själv
  • -
  • Mapprenumerationer
  • -
  • Synkronisera alla mappar
  • -
  • Inställning av svarsadress
  • -
  • Tangentbordsgenvägar
  • -
  • Bättre stöd för IMAP
  • -
  • Spara bilagor till minneskort
  • -
  • Tömma papperskorgen
  • -
  • Meddelandesortering
  • -
  • …och mycket annat
  • -
-

-Observera att K-9 inte stöder gratiskonton på Hotmail och har, som så många andra e-postklienter, några svårigheter att prata med Microsoft Exchange. -

-Skicka in felrapporter, bidra med nya funktioner och ställ frågor på -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nSkickat från min Android-enhet med K-9 Mail. Ursäkta min korthet. Kontot \"%s\" kommer att tas bort från K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-tr/strings.xml b/app/ui/legacy/src/main/res/values-tr/strings.xml index 1909bfd3bb..537b09060d 100644 --- a/app/ui/legacy/src/main/res/values-tr/strings.xml +++ b/app/ui/legacy/src/main/res/values-tr/strings.xml @@ -27,38 +27,7 @@ Bu sürümdeki yenilikleri öğrenin - - K-9 Posta\'ya Hoşgeldiniz - -K-9 Posta, Android için güçlü ve özgür bir e-posta istemcisidir. -

-Geliştirilmiş özellikler içerir: -

-
    -
  • IMAP IDLE kullanılarak gelen posta anında gösteriliyor
  • -
  • Daha iyi başarım
  • -
  • İletiye tekrar işlem
  • -
  • E-posta imzaları
  • -
  • Bcc-to-self
  • -
  • Klasör kayıtları
  • -
  • Tüm klasörler eşzamanlanır
  • -
  • Yanıt adresi yapılandırması
  • -
  • Klavye kısayolları
  • -
  • Daha iyi IMAP desteği
  • -
  • Eklentileri SD karta kaydetme
  • -
  • Çöpü Boşalt
  • -
  • İleti sıralama
  • -
  • …ve daha fazlası
  • -
-

-K-9\'un çoğu ücretsiz Hotmail hesabını desteklemediğini ve pek çok e-posta istemcisi gibi -Microsoft Exchange ile konuşurken kimi tuhaflıklar yaşadığını lütfen aklınızın bir köşesine yazın. -

Lütfen yeni özelliklere katkıda bulunmak ve soru sormak için hata raporu bildiriniz -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nAndroid için K-9 Posta\'dan gönderildi. Lütfen bu kısa notumu mazur görün. Hesap \"%s\" K-9 Mail\'den kaldırılacak. diff --git a/app/ui/legacy/src/main/res/values-uk/strings.xml b/app/ui/legacy/src/main/res/values-uk/strings.xml index 2fa2020932..b9059c4b28 100644 --- a/app/ui/legacy/src/main/res/values-uk/strings.xml +++ b/app/ui/legacy/src/main/res/values-uk/strings.xml @@ -28,39 +28,7 @@ Дізнатися, що нового у цьому релізі Показати - - Ласкаво просимо до K-9 Mail - -K-9 Mail — це вільний клієнт електронної пошти для Android з багатьма можливостями. -

-Його найкращі можливості: -

-
    -
  • Миттєва пошта з використанням IMAP IDLE
  • -
  • Краща продуктивність
  • -
  • Відповіді і пересилання повідомлень
  • -
  • Підписи у електронних листах
  • -
  • Прихована копія собі
  • -
  • Підписка на певні теки
  • -
  • Синхронізація всіх тек
  • -
  • Налаштування адреси для відповіді
  • -
  • Клавіатурні скорочення
  • -
  • Покращена підтримка IMAP
  • -
  • Збереження вкладень на SD-карту
  • -
  • Очищення кошика
  • -
  • Сортування повідомлень
  • -
  • …і більше
  • -
-

-Зверніть увагу, що K-9 не підтримує більшість безкоштовних облікових записів Hotmail, а також, як і багато поштових програм, виявляє -деякі дивацтва при роботі з Microsoft Exchange. -

-Будь ласка, звітуйте про недоліки, пропонуйте нові можливості та задавайте запитання на -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \nВідправлено з мого Android-пристрою за допомогою додатка K-9 Mail. Вибачте за стислість. Обліковий запис \"%s\" буде вилучено з K-9 Mail. diff --git a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml index 086f61bd02..432862fd2e 100644 --- a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml +++ b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml @@ -28,39 +28,7 @@ 了解此版本的新增功能 查看 - - 欢迎使用 K-9 Mail - -K-9 Mail 是 Android 上一款功能强大的免费邮件客户端。 -

-其改进的功能包括: -

-
    -
  • 支持通过 IMAP IDLE 推送邮件
  • -
  • 更好的性能
  • -
  • 消息归档
  • -
  • 邮件签名
  • -
  • 密送自己
  • -
  • 邮件夹订阅
  • -
  • 同步所有邮件夹
  • -
  • 回复地址配置
  • -
  • 快捷键
  • -
  • 更好的 IMAP 支持
  • -
  • 保存附件到 SD 卡
  • -
  • 清空回收站
  • -
  • 消息排序
  • -
  • 以及更多…
  • -
-

-请注意 K-9 不支持大部分免费 Hotmail 账户,而且和其他大部分邮件客户端一样, -在使用 Microsoft Exchange 协议时会有一些问题。 -

-请到下述网址提交问题报告,新功能建议或者提问: -https://github.com/k9mail/k-9/。 -

- ]]>
- + -- \n使用 K-9 Mail 发送自我的Android设备。 即将从 K-9 Mail 中移除账户“%s”。 diff --git a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml index b81fb7c366..d864c41e37 100644 --- a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml +++ b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml @@ -28,39 +28,7 @@ 了解此版本的新增功能 檢視 - - 歡迎使用 K-9 Mail - -K-9 Mail 是 Android 上一款功能強大,免費的電子郵件用戶端。 -

-其改進的功能包括: -

-
    -
  • 支援 IMAP IDLE 指令推送郵件
  • -
  • 更好的性能
  • -
  • 訊息重新轉寄封存
  • -
  • 郵件簽名
  • -
  • 密件副本寄送給自己
  • -
  • 信件匣訂閱
  • -
  • 同步所有信件匣
  • -
  • 回覆地址設定
  • -
  • 快速鍵
  • -
  • 更好的 IMAP 支援
  • -
  • 儲存附件至 SD 卡
  • -
  • 清空垃圾桶
  • -
  • 訊息排序
  • -
  • …以及更多
  • -
-

-請注意 K-9 不支援大部分免費 Hotmail 帳號,而且和其他大部分郵件客戶端一樣, -在使用 Microsoft Exchange 協定時會有一些問題。 -

-請到下述網址提交問題報告,新功能建議或者提問: -https://github.com/k9mail/k-9/. -

- ]]>
- + -- \n使用 K-9 Mail 寄送。來自我的 Android 裝置。 帳號「%s」將從 K-9 Mail 中刪除。 diff --git a/app/ui/legacy/src/main/res/values/strings.xml b/app/ui/legacy/src/main/res/values/strings.xml index 55a1e161e3..8e1e5b9430 100644 --- a/app/ui/legacy/src/main/res/values/strings.xml +++ b/app/ui/legacy/src/main/res/values/strings.xml @@ -35,40 +35,6 @@ View - - Welcome to K-9 Mail - -K-9 Mail is a powerful free email client for Android. -

-Its improved features include: -

-
    -
  • Push mail using IMAP IDLE
  • -
  • Better performance
  • -
  • Message refiling
  • -
  • Email signatures
  • -
  • Bcc-to-self
  • -
  • Folder subscriptions
  • -
  • All folder synchronization
  • -
  • Return-address configuration
  • -
  • Keyboard shortcuts
  • -
  • Better IMAP support
  • -
  • Saving attachments to SD
  • -
  • Empty Trash
  • -
  • Message sorting
  • -
  • …and more
  • -
-

-Please note that K-9 does not support most free Hotmail accounts and, like many mail clients, has -some quirks when talking to Microsoft Exchange. -

-Please submit bug reports, contribute new features and ask questions at -https://github.com/k9mail/k-9/. -

- ]]>
- - -- \nSent from my Android device with K-9 Mail. Please excuse my brevity. -- GitLab From d9125d3c0289db5887b5eeae8b36df4165bf20ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Fri, 15 Sep 2023 14:03:33 +0200 Subject: [PATCH 70/94] Change order of events --- .../k9mail/feature/account/setup/ui/AccountSetupContract.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupContract.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupContract.kt index 8d8651de75..7caefbdd46 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupContract.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/ui/AccountSetupContract.kt @@ -21,12 +21,11 @@ interface AccountSetupContract { ) sealed interface Event { - object OnNext : Event - data class OnAutoDiscoveryFinished( val isAutomaticConfig: Boolean, ) : Event + object OnNext : Event object OnBack : Event } -- GitLab From e9a73c905cb6e9ada9ff25d3d46936d8da19a71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Mon, 25 Sep 2023 16:07:36 +0200 Subject: [PATCH 71/94] Add Coroutines to JVM main and test --- gradle/libs.versions.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8c3114ddde..48895a6e9e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -161,6 +161,7 @@ detekt-plugin-compose = "io.nlopez.compose.rules:detekt:0.1.11" shared-jvm-main = [ "koin-core", "kotlinx-datetime", + "kotlinx-coroutines-core", ] shared-jvm-android = [ "androidx-core", @@ -190,6 +191,7 @@ shared-jvm-androidtest-compose = [ ] shared-jvm-test = [ "kotlin-test", + "kotlinx-coroutines-test", "junit", "assertk", "mockito-core", -- GitLab From eff8b25a3a24c5ab8f74e6ff7924743a010a9d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Mon, 11 Sep 2023 17:52:28 +0200 Subject: [PATCH 72/94] Add AccountLoader --- .../k9mail/feature/preview/FeatureModule.kt | 2 + .../preview/account/InMemoryAccountStore.kt | 24 ++++++++- .../java/com/fsck/k9/account/AccountLoader.kt | 50 +++++++++++++++++++ .../java/com/fsck/k9/account/AccountModule.kt | 7 +++ .../common/AccountCommonExternalContract.kt | 10 ++++ .../account/common/AccountCommonModule.kt | 1 - .../IncomingServerSettingsViewModelTest.kt | 4 +- .../OutgoingServerSettingsViewModelTest.kt | 4 +- .../ServerValidationModuleKtTest.kt | 7 ++- .../IncomingServerValidationViewModelTest.kt | 4 +- .../OutgoingServerValidationViewModelTest.kt | 4 +- .../account/setup/AccountSetupModuleKtTest.kt | 3 ++ 12 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt create mode 100644 feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonExternalContract.kt diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt index 43ddc813f0..e01d782474 100644 --- a/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt @@ -1,6 +1,7 @@ package app.k9mail.feature.preview import app.k9mail.core.common.oauth.OAuthConfigurationFactory +import app.k9mail.feature.account.common.AccountCommonExternalContract import app.k9mail.feature.account.edit.AccountEditExternalContract import app.k9mail.feature.account.setup.AccountSetupExternalContract import app.k9mail.feature.account.setup.featureAccountSetupModule @@ -23,6 +24,7 @@ val accountModule: Module = module { single { InMemoryAccountStore() } .binds( arrayOf( + AccountCommonExternalContract.AccountLoader::class, AccountSetupExternalContract.AccountCreator::class, AccountEditExternalContract.AccountUpdater::class, ), diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt index 40787f79f9..b3691cd62a 100644 --- a/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt @@ -1,6 +1,9 @@ package app.k9mail.feature.preview.account +import app.k9mail.feature.account.common.AccountCommonExternalContract.AccountLoader import app.k9mail.feature.account.common.domain.entity.Account +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.edit.AccountEditExternalContract.AccountUpdater import app.k9mail.feature.account.edit.AccountEditExternalContract.AccountUpdater.AccountUpdaterResult import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCreator @@ -8,7 +11,15 @@ import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCrea class InMemoryAccountStore( private val accountMap: MutableMap = mutableMapOf(), -) : AccountCreator, AccountUpdater { +) : AccountCreator, AccountUpdater, AccountLoader { + + suspend fun load(accountUuid: String): Account? { + return accountMap[accountUuid] + } + + override suspend fun loadAccount(accountUuid: String): AccountState? { + return accountMap[accountUuid]?.let { mapToAccountState(it) } + } override suspend fun createAccount(account: Account): AccountCreatorResult { accountMap[account.uuid] = account @@ -25,4 +36,15 @@ class InMemoryAccountStore( AccountUpdaterResult.Success(account.uuid) } } + + private fun mapToAccountState(account: Account): AccountState { + return AccountState( + uuid = account.uuid, + emailAddress = account.emailAddress, + incomingServerSettings = account.incomingServerSettings, + outgoingServerSettings = account.outgoingServerSettings, + authorizationState = account.authorizationState?.let { AuthorizationState(it) }, + options = account.options, + ) + } } diff --git a/app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt b/app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt new file mode 100644 index 0000000000..d333f0eb4b --- /dev/null +++ b/app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt @@ -0,0 +1,50 @@ +package com.fsck.k9.account + +import app.k9mail.feature.account.common.AccountCommonExternalContract +import app.k9mail.feature.account.common.domain.entity.Account +import app.k9mail.feature.account.common.domain.entity.AccountOptions +import com.fsck.k9.Preferences +import com.fsck.k9.logging.Timber +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import com.fsck.k9.Account as K9Account + +class AccountLoader( + private val preferences: Preferences, + private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO, +) : AccountCommonExternalContract.AccountLoader { + + @Suppress("TooGenericExceptionCaught") + override suspend fun loadAccount(accountUuid: String): AccountState? { + return try { + withContext(coroutineDispatcher) { + load(accountUuid) + } + } catch (e: Exception) { + Timber.e(e, "Error while loading account") + + null + } + } + + val existingAccount = preferences.getAccount(accountUuid) + private fun load(accountUuid: String): AccountState? { + + return if (existingAccount != null) { + mapToAccount(existingAccount) + } else { + null + } + } + + private fun mapToAccount(account: K9Account): AccountState { + return AccountState( + uuid = account.uuid, + emailAddress = account.email, + incomingServerSettings = account.incomingServerSettings, + outgoingServerSettings = account.outgoingServerSettings, + authorizationState = AuthorizationState(account.oAuthState), + ) + } +} diff --git a/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt b/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt index a695964a63..573d912ace 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt @@ -1,5 +1,6 @@ package com.fsck.k9.account +import app.k9mail.feature.account.common.AccountCommonExternalContract import app.k9mail.feature.account.edit.AccountEditExternalContract import app.k9mail.feature.account.setup.AccountSetupExternalContract import org.koin.android.ext.koin.androidApplication @@ -21,6 +22,12 @@ val newAccountModule = module { ) } + factory { + AccountLoader( + preferences = get(), + ) + } + factory { AccountUpdater( preferences = get(), diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonExternalContract.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonExternalContract.kt new file mode 100644 index 0000000000..a24fe20969 --- /dev/null +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonExternalContract.kt @@ -0,0 +1,10 @@ +package app.k9mail.feature.account.common + +import app.k9mail.feature.account.common.domain.entity.AccountState + +interface AccountCommonExternalContract { + + fun interface AccountLoader { + suspend fun loadAccount(accountUuid: String): AccountState? + } +} diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonModule.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonModule.kt index 5ca9067c24..b186198f89 100644 --- a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonModule.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonModule.kt @@ -11,7 +11,6 @@ import org.koin.dsl.module val featureAccountCommonModule: Module = module { includes(coreCommonModule) - // TODO: we need to provide one for setup and edit later on single { InMemoryAccountStateRepository() }.binds(arrayOf(AccountDomainContract.AccountStateRepository::class, AuthStateStorage::class)) diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt index dd225e0d81..d9ea32523d 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModelTest.kt @@ -50,7 +50,9 @@ class IncomingServerSettingsViewModelTest { extra = emptyMap(), ), ) - val repository = InMemoryAccountStateRepository(AccountState()) + val repository = InMemoryAccountStateRepository( + state = AccountState(), + ) val testSubject = createTestSubject( repository = repository, ) diff --git a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt index a055a0651c..988a94e5b2 100644 --- a/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt +++ b/feature/account/server/settings/src/test/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModelTest.kt @@ -48,7 +48,9 @@ class OutgoingServerSettingsViewModelTest { extra = emptyMap(), ), ) - val repository = InMemoryAccountStateRepository(AccountState()) + val repository = InMemoryAccountStateRepository( + state = AccountState(), + ) val testSubject = createTestSubject( repository = repository, ) diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt index 07258f240c..ecc653b9fc 100644 --- a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt @@ -2,6 +2,7 @@ package app.k9mail.feature.account.server.validation import android.content.Context import app.k9mail.core.common.oauth.OAuthConfigurationFactory +import app.k9mail.feature.account.common.AccountCommonExternalContract import app.k9mail.feature.account.common.domain.AccountDomainContract import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.server.certificate.domain.ServerCertificateDomainContract @@ -22,7 +23,7 @@ import org.koin.dsl.module import org.koin.test.KoinTest import org.koin.test.check.checkModules import org.koin.test.verify.verify -import org.mockito.Mockito +import org.mockito.Mockito.mock import org.robolectric.RobolectricTestRunner import org.robolectric.RuntimeEnvironment @@ -42,7 +43,8 @@ class ServerValidationModuleKtTest : KoinTest { } } } - single { Mockito.mock() } + single { mock() } + factory { mock() } single(named("ClientIdAppName")) { "App Name" } } @@ -53,6 +55,7 @@ class ServerValidationModuleKtTest : KoinTest { extraTypes = listOf( ServerValidationContract.State::class, AccountDomainContract.AccountStateRepository::class, + AccountCommonExternalContract.AccountLoader::class, ServerCertificateDomainContract.ServerCertificateErrorRepository::class, ServerCertificateErrorContract.State::class, AccountState::class, diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModelTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModelTest.kt index 51b150e295..82ae20d0e1 100644 --- a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModelTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/IncomingServerValidationViewModelTest.kt @@ -47,7 +47,9 @@ class IncomingServerValidationViewModelTest : BaseServerValidationViewModelTest< delay(50) serverSettingsValidationResult }, - accountStateRepository = InMemoryAccountStateRepository(accountState), + accountStateRepository = InMemoryAccountStateRepository( + state = accountState, + ), authorizationStateRepository = { true }, certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = FakeAccountOAuthViewModel(), diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModelTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModelTest.kt index 068fbf43f3..408a95ce15 100644 --- a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModelTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ui/OutgoingServerValidationViewModelTest.kt @@ -47,7 +47,9 @@ class OutgoingServerValidationViewModelTest : BaseServerValidationViewModelTest< delay(50) serverSettingsValidationResult }, - accountStateRepository = InMemoryAccountStateRepository(accountState), + accountStateRepository = InMemoryAccountStateRepository( + state = accountState, + ), authorizationStateRepository = { true }, certificateErrorRepository = InMemoryServerCertificateErrorRepository(), oAuthViewModel = FakeAccountOAuthViewModel(), diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index c775657baa..2c0390023b 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -2,6 +2,7 @@ package app.k9mail.feature.account.setup import android.content.Context import app.k9mail.core.common.oauth.OAuthConfigurationFactory +import app.k9mail.feature.account.common.AccountCommonExternalContract import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.oauth.ui.AccountOAuthContract import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract @@ -55,12 +56,14 @@ class AccountSetupModuleKtTest : KoinTest { } } single { mock() } + single { mock() } } @Test fun `should have a valid di module`() { featureAccountSetupModule.verify( extraTypes = listOf( + AccountCommonExternalContract.AccountLoader::class, AccountSetupContract.State::class, AccountAutoDiscoveryContract.State::class, AccountOAuthContract.State::class, -- GitLab From f0353eb743325d8ca6faae9d5d6bbc967a3b140e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Fri, 22 Sep 2023 16:31:28 +0200 Subject: [PATCH 73/94] Change to AccountManager and add test for AccountLoader --- .../java/com/fsck/k9/account/AccountLoader.kt | 16 ++-- .../java/com/fsck/k9/account/AccountModule.kt | 2 +- .../com/fsck/k9/account/AccountLoaderTest.kt | 82 +++++++++++++++++++ .../com/fsck/k9/account/FakeAccountManager.kt | 42 ++++++++++ 4 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 app/k9mail/src/test/java/com/fsck/k9/account/AccountLoaderTest.kt create mode 100644 app/k9mail/src/test/java/com/fsck/k9/account/FakeAccountManager.kt diff --git a/app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt b/app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt index d333f0eb4b..b9d4e8be70 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt @@ -1,17 +1,17 @@ package com.fsck.k9.account import app.k9mail.feature.account.common.AccountCommonExternalContract -import app.k9mail.feature.account.common.domain.entity.Account -import app.k9mail.feature.account.common.domain.entity.AccountOptions -import com.fsck.k9.Preferences +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState import com.fsck.k9.logging.Timber +import com.fsck.k9.preferences.AccountManager import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import com.fsck.k9.Account as K9Account class AccountLoader( - private val preferences: Preferences, + private val accountManager: AccountManager, private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO, ) : AccountCommonExternalContract.AccountLoader { @@ -28,14 +28,8 @@ class AccountLoader( } } - val existingAccount = preferences.getAccount(accountUuid) private fun load(accountUuid: String): AccountState? { - - return if (existingAccount != null) { - mapToAccount(existingAccount) - } else { - null - } + return accountManager.getAccount(accountUuid)?.let { mapToAccount(it) } } private fun mapToAccount(account: K9Account): AccountState { diff --git a/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt b/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt index 573d912ace..5d960aac77 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt @@ -24,7 +24,7 @@ val newAccountModule = module { factory { AccountLoader( - preferences = get(), + accountManager = get(), ) } diff --git a/app/k9mail/src/test/java/com/fsck/k9/account/AccountLoaderTest.kt b/app/k9mail/src/test/java/com/fsck/k9/account/AccountLoaderTest.kt new file mode 100644 index 0000000000..f20d548bea --- /dev/null +++ b/app/k9mail/src/test/java/com/fsck/k9/account/AccountLoaderTest.kt @@ -0,0 +1,82 @@ +package com.fsck.k9.account + +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState +import assertk.assertThat +import assertk.assertions.isEqualTo +import assertk.assertions.isNull +import com.fsck.k9.Identity +import com.fsck.k9.mail.AuthType +import com.fsck.k9.mail.ConnectionSecurity +import com.fsck.k9.mail.ServerSettings +import kotlinx.coroutines.test.runTest +import org.junit.Test +import com.fsck.k9.Account as K9Account + +class AccountLoaderTest { + + @Test + fun `loadAccount() should return null when accountManager returns null`() = runTest { + val accountManager = FakeAccountManager() + val accountLoader = AccountLoader(accountManager) + + val result = accountLoader.loadAccount("accountUuid") + + assertThat(result).isNull() + } + + @Test + fun `loadAccount() should return account when present in accountManager`() = runTest { + val accounts = mapOf( + "accountUuid" to K9Account( + uuid = "accountUuid", + ).also { + it.identities = mutableListOf(Identity()) + it.email = "emailAddress" + it.incomingServerSettings = INCOMING_SERVER_SETTINGS + it.outgoingServerSettings = OUTGOING_SERVER_SETTINGS + it.oAuthState = "oAuthState" + }, + ) + val accountManager = FakeAccountManager(accounts = accounts) + val accountLoader = AccountLoader(accountManager) + + val result = accountLoader.loadAccount("accountUuid") + + assertThat(result).isEqualTo( + AccountState( + uuid = "accountUuid", + emailAddress = "emailAddress", + incomingServerSettings = INCOMING_SERVER_SETTINGS, + outgoingServerSettings = OUTGOING_SERVER_SETTINGS, + authorizationState = AuthorizationState("oAuthState"), + ), + ) + } + + private companion object { + val INCOMING_SERVER_SETTINGS = ServerSettings( + type = "imap", + host = "imap.example.org", + port = 143, + connectionSecurity = ConnectionSecurity.SSL_TLS_REQUIRED, + authenticationType = AuthType.PLAIN, + username = "username", + password = "password", + clientCertificateAlias = null, + extra = emptyMap(), + ) + + val OUTGOING_SERVER_SETTINGS = ServerSettings( + type = "smtp", + host = "smtp.example.org", + port = 587, + connectionSecurity = ConnectionSecurity.SSL_TLS_REQUIRED, + authenticationType = AuthType.PLAIN, + username = "username", + password = "password", + clientCertificateAlias = null, + extra = emptyMap(), + ) + } +} diff --git a/app/k9mail/src/test/java/com/fsck/k9/account/FakeAccountManager.kt b/app/k9mail/src/test/java/com/fsck/k9/account/FakeAccountManager.kt new file mode 100644 index 0000000000..d22868e2f0 --- /dev/null +++ b/app/k9mail/src/test/java/com/fsck/k9/account/FakeAccountManager.kt @@ -0,0 +1,42 @@ +package com.fsck.k9.account + +import com.fsck.k9.Account +import com.fsck.k9.AccountRemovedListener +import com.fsck.k9.AccountsChangeListener +import com.fsck.k9.preferences.AccountManager +import kotlinx.coroutines.flow.Flow + +class FakeAccountManager( + private val accounts: Map = emptyMap(), +) : AccountManager { + + override fun getAccountsFlow(): Flow> { + TODO("Not yet implemented") + } + + override fun getAccount(accountUuid: String): Account? = accounts[accountUuid] + + override fun getAccountFlow(accountUuid: String): Flow { + TODO("Not yet implemented") + } + + override fun addAccountRemovedListener(listener: AccountRemovedListener) { + TODO("Not yet implemented") + } + + override fun moveAccount(account: Account, newPosition: Int) { + TODO("Not yet implemented") + } + + override fun addOnAccountsChangeListener(accountsChangeListener: AccountsChangeListener) { + TODO("Not yet implemented") + } + + override fun removeOnAccountsChangeListener(accountsChangeListener: AccountsChangeListener) { + TODO("Not yet implemented") + } + + override fun saveAccount(account: Account) { + TODO("Not yet implemented") + } +} -- GitLab From 496a64c04e4c449a49db48ce7ac667b8e02b71f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Mon, 25 Sep 2023 16:21:48 +0200 Subject: [PATCH 74/94] Change name to AccountStateLoader --- .../k9mail/feature/preview/FeatureModule.kt | 2 +- .../preview/account/InMemoryAccountStore.kt | 6 ++-- .../java/com/fsck/k9/account/AccountModule.kt | 4 +-- ...AccountLoader.kt => AccountStateLoader.kt} | 10 +++---- ...oaderTest.kt => AccountStateLoaderTest.kt} | 30 +++++++++---------- .../common/AccountCommonExternalContract.kt | 4 +-- .../ServerValidationModuleKtTest.kt | 4 +-- .../account/setup/AccountSetupModuleKtTest.kt | 4 +-- 8 files changed, 31 insertions(+), 33 deletions(-) rename app/k9mail/src/main/java/com/fsck/k9/account/{AccountLoader.kt => AccountStateLoader.kt} (84%) rename app/k9mail/src/test/java/com/fsck/k9/account/{AccountLoaderTest.kt => AccountStateLoaderTest.kt} (69%) diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt index e01d782474..1a5676f0d3 100644 --- a/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt @@ -24,7 +24,7 @@ val accountModule: Module = module { single { InMemoryAccountStore() } .binds( arrayOf( - AccountCommonExternalContract.AccountLoader::class, + AccountCommonExternalContract.AccountStateLoader::class, AccountSetupExternalContract.AccountCreator::class, AccountEditExternalContract.AccountUpdater::class, ), diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt index b3691cd62a..fdb4136509 100644 --- a/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/account/InMemoryAccountStore.kt @@ -1,6 +1,6 @@ package app.k9mail.feature.preview.account -import app.k9mail.feature.account.common.AccountCommonExternalContract.AccountLoader +import app.k9mail.feature.account.common.AccountCommonExternalContract.AccountStateLoader import app.k9mail.feature.account.common.domain.entity.Account import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.entity.AuthorizationState @@ -11,13 +11,13 @@ import app.k9mail.feature.account.setup.AccountSetupExternalContract.AccountCrea class InMemoryAccountStore( private val accountMap: MutableMap = mutableMapOf(), -) : AccountCreator, AccountUpdater, AccountLoader { +) : AccountCreator, AccountUpdater, AccountStateLoader { suspend fun load(accountUuid: String): Account? { return accountMap[accountUuid] } - override suspend fun loadAccount(accountUuid: String): AccountState? { + override suspend fun loadAccountState(accountUuid: String): AccountState? { return accountMap[accountUuid]?.let { mapToAccountState(it) } } diff --git a/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt b/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt index 5d960aac77..677c544e7e 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/account/AccountModule.kt @@ -22,8 +22,8 @@ val newAccountModule = module { ) } - factory { - AccountLoader( + factory { + AccountStateLoader( accountManager = get(), ) } diff --git a/app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt b/app/k9mail/src/main/java/com/fsck/k9/account/AccountStateLoader.kt similarity index 84% rename from app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt rename to app/k9mail/src/main/java/com/fsck/k9/account/AccountStateLoader.kt index b9d4e8be70..71b30ec470 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/account/AccountLoader.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/account/AccountStateLoader.kt @@ -10,13 +10,13 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import com.fsck.k9.Account as K9Account -class AccountLoader( +class AccountStateLoader( private val accountManager: AccountManager, private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO, -) : AccountCommonExternalContract.AccountLoader { +) : AccountCommonExternalContract.AccountStateLoader { @Suppress("TooGenericExceptionCaught") - override suspend fun loadAccount(accountUuid: String): AccountState? { + override suspend fun loadAccountState(accountUuid: String): AccountState? { return try { withContext(coroutineDispatcher) { load(accountUuid) @@ -29,10 +29,10 @@ class AccountLoader( } private fun load(accountUuid: String): AccountState? { - return accountManager.getAccount(accountUuid)?.let { mapToAccount(it) } + return accountManager.getAccount(accountUuid)?.let { mapToAccountState(it) } } - private fun mapToAccount(account: K9Account): AccountState { + private fun mapToAccountState(account: K9Account): AccountState { return AccountState( uuid = account.uuid, emailAddress = account.email, diff --git a/app/k9mail/src/test/java/com/fsck/k9/account/AccountLoaderTest.kt b/app/k9mail/src/test/java/com/fsck/k9/account/AccountStateLoaderTest.kt similarity index 69% rename from app/k9mail/src/test/java/com/fsck/k9/account/AccountLoaderTest.kt rename to app/k9mail/src/test/java/com/fsck/k9/account/AccountStateLoaderTest.kt index f20d548bea..be7b5f9402 100644 --- a/app/k9mail/src/test/java/com/fsck/k9/account/AccountLoaderTest.kt +++ b/app/k9mail/src/test/java/com/fsck/k9/account/AccountStateLoaderTest.kt @@ -5,43 +5,41 @@ import app.k9mail.feature.account.common.domain.entity.AuthorizationState import assertk.assertThat import assertk.assertions.isEqualTo import assertk.assertions.isNull +import com.fsck.k9.Account import com.fsck.k9.Identity import com.fsck.k9.mail.AuthType import com.fsck.k9.mail.ConnectionSecurity import com.fsck.k9.mail.ServerSettings import kotlinx.coroutines.test.runTest import org.junit.Test -import com.fsck.k9.Account as K9Account -class AccountLoaderTest { +class AccountStateLoaderTest { @Test - fun `loadAccount() should return null when accountManager returns null`() = runTest { + fun `loadAccountState() should return null when accountManager returns null`() = runTest { val accountManager = FakeAccountManager() - val accountLoader = AccountLoader(accountManager) + val accountLoader = AccountStateLoader(accountManager) - val result = accountLoader.loadAccount("accountUuid") + val result = accountLoader.loadAccountState("accountUuid") assertThat(result).isNull() } @Test - fun `loadAccount() should return account when present in accountManager`() = runTest { + fun `loadAccountState() should return account when present in accountManager`() = runTest { val accounts = mapOf( - "accountUuid" to K9Account( - uuid = "accountUuid", - ).also { - it.identities = mutableListOf(Identity()) - it.email = "emailAddress" - it.incomingServerSettings = INCOMING_SERVER_SETTINGS - it.outgoingServerSettings = OUTGOING_SERVER_SETTINGS - it.oAuthState = "oAuthState" + "accountUuid" to Account(uuid = "accountUuid").apply { + identities = mutableListOf(Identity()) + email = "emailAddress" + incomingServerSettings = INCOMING_SERVER_SETTINGS + outgoingServerSettings = OUTGOING_SERVER_SETTINGS + oAuthState = "oAuthState" }, ) val accountManager = FakeAccountManager(accounts = accounts) - val accountLoader = AccountLoader(accountManager) + val accountLoader = AccountStateLoader(accountManager) - val result = accountLoader.loadAccount("accountUuid") + val result = accountLoader.loadAccountState("accountUuid") assertThat(result).isEqualTo( AccountState( diff --git a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonExternalContract.kt b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonExternalContract.kt index a24fe20969..3d8fe3c18f 100644 --- a/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonExternalContract.kt +++ b/feature/account/common/src/main/kotlin/app/k9mail/feature/account/common/AccountCommonExternalContract.kt @@ -4,7 +4,7 @@ import app.k9mail.feature.account.common.domain.entity.AccountState interface AccountCommonExternalContract { - fun interface AccountLoader { - suspend fun loadAccount(accountUuid: String): AccountState? + fun interface AccountStateLoader { + suspend fun loadAccountState(accountUuid: String): AccountState? } } diff --git a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt index ecc653b9fc..deff0f85db 100644 --- a/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt +++ b/feature/account/server/validation/src/test/kotlin/app/k9mail/feature/account/server/validation/ServerValidationModuleKtTest.kt @@ -44,7 +44,7 @@ class ServerValidationModuleKtTest : KoinTest { } } single { mock() } - factory { mock() } + factory { mock() } single(named("ClientIdAppName")) { "App Name" } } @@ -55,7 +55,7 @@ class ServerValidationModuleKtTest : KoinTest { extraTypes = listOf( ServerValidationContract.State::class, AccountDomainContract.AccountStateRepository::class, - AccountCommonExternalContract.AccountLoader::class, + AccountCommonExternalContract.AccountStateLoader::class, ServerCertificateDomainContract.ServerCertificateErrorRepository::class, ServerCertificateErrorContract.State::class, AccountState::class, diff --git a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt index 2c0390023b..21acaf2194 100644 --- a/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt +++ b/feature/account/setup/src/test/kotlin/app/k9mail/feature/account/setup/AccountSetupModuleKtTest.kt @@ -56,14 +56,14 @@ class AccountSetupModuleKtTest : KoinTest { } } single { mock() } - single { mock() } + single { mock() } } @Test fun `should have a valid di module`() { featureAccountSetupModule.verify( extraTypes = listOf( - AccountCommonExternalContract.AccountLoader::class, + AccountCommonExternalContract.AccountStateLoader::class, AccountSetupContract.State::class, AccountAutoDiscoveryContract.State::class, AccountOAuthContract.State::class, -- GitLab From be2c35ff307ae902bb7d1d8ba0d938e05c26a300 Mon Sep 17 00:00:00 2001 From: cketti Date: Tue, 26 Sep 2023 16:25:32 +0200 Subject: [PATCH 75/94] Fix navigation in settings list screen --- .../java/com/fsck/k9/ui/settings/SettingsListFragment.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/SettingsListFragment.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/SettingsListFragment.kt index fdbaaaa537..d257648e71 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/SettingsListFragment.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/SettingsListFragment.kt @@ -11,6 +11,7 @@ import android.widget.Toast import androidx.annotation.AttrRes import androidx.annotation.IdRes import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -149,10 +150,10 @@ class SettingsListFragment : Fragment(), ItemTouchCallback { is AccountItem -> launchAccountSettings(item.account) is UrlActionItem -> openUrl(item.url) is SettingsActionItem -> { - if ( - item.navigationAction == R.id.action_settingsListScreen_to_addAccountScreen - ) { + if (item.navigationAction == R.id.action_settingsListScreen_to_addAccountScreen) { FeatureLauncherActivity.launchSetupAccount(requireActivity()) + } else { + findNavController().navigate(item.navigationAction) } } } -- GitLab From 9809fa523e174dea7a86a53fd2c3bdb989888880 Mon Sep 17 00:00:00 2001 From: mhfarzaneganbb Date: Sat, 12 Aug 2023 06:24:08 -0500 Subject: [PATCH 76/94] Remove the theme attribute messageViewBackgroundColor and all code associated with it --- .../src/main/java/com/fsck/k9/activity/MessageCompose.java | 2 +- app/ui/legacy/src/main/res/layout/message.xml | 1 - app/ui/legacy/src/main/res/values/attrs.xml | 1 - app/ui/legacy/src/main/res/values/themes.xml | 2 -- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageCompose.java b/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageCompose.java index 6115d8f584..af860e40bf 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageCompose.java +++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageCompose.java @@ -272,7 +272,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, // background color needs to be forced //TODO: Change themes to use appropriate background colors that don't need overriding. TypedValue outValue = new TypedValue(); - themeContext.getTheme().resolveAttribute(R.attr.messageViewBackgroundColor, outValue, true); + themeContext.getTheme().resolveAttribute(android.R.attr.windowBackground, outValue, true); contentView.setBackgroundColor(outValue.data); diff --git a/app/ui/legacy/src/main/res/layout/message.xml b/app/ui/legacy/src/main/res/layout/message.xml index 894f69cf42..3d206d1b58 100644 --- a/app/ui/legacy/src/main/res/layout/message.xml +++ b/app/ui/legacy/src/main/res/layout/message.xml @@ -8,7 +8,6 @@ android:layout_height="match_parent" android:orientation="vertical" android:layout_weight="1" - android:background="?attr/messageViewBackgroundColor" tools:context=".messageview.MessageViewFragment"> - diff --git a/app/ui/legacy/src/main/res/values/themes.xml b/app/ui/legacy/src/main/res/values/themes.xml index a15ab543a2..58dba5008d 100644 --- a/app/ui/legacy/src/main/res/values/themes.xml +++ b/app/ui/legacy/src/main/res/values/themes.xml @@ -129,7 +129,6 @@ @color/material_purple_500 #fbbc04 - #ffffffff @drawable/ic_person_add #ffcccccc #e8e8e8 @@ -296,7 +295,6 @@ @color/material_purple_600 #fdd663 - #000000 @drawable/ic_person_add #ff555555 #313131 -- GitLab From 11abe6f0dff9d379b6964f896f5d7df71373fb6c Mon Sep 17 00:00:00 2001 From: mhfarzaneganbb Date: Sat, 12 Aug 2023 06:26:10 -0500 Subject: [PATCH 77/94] Change MessageWebView.configure() to set the WebView's background color to the theme background color --- .../legacy/src/main/java/com/fsck/k9/view/MessageWebView.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/view/MessageWebView.kt b/app/ui/legacy/src/main/java/com/fsck/k9/view/MessageWebView.kt index 47efd8a3fe..a070d362f2 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/view/MessageWebView.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/view/MessageWebView.kt @@ -3,6 +3,7 @@ package com.fsck.k9.view import android.content.Context import android.content.pm.PackageManager import android.util.AttributeSet +import android.util.TypedValue import android.webkit.WebSettings.LayoutAlgorithm import android.webkit.WebSettings.RenderPriority import android.webkit.WebView @@ -34,7 +35,10 @@ class MessageWebView : WebView, KoinComponent { isLongClickable = true if (config.useDarkMode) { - setBackgroundColor(0xff000000L.toInt()) + val typedValue = TypedValue() + context.theme.resolveAttribute(android.R.attr.windowBackground, typedValue, true) + val backgroundColor = typedValue.data + setBackgroundColor(backgroundColor) } with(settings) { -- GitLab From 0a99643a7a25ba5664de30e4bb0607c3f654010b Mon Sep 17 00:00:00 2001 From: cketti Date: Tue, 26 Sep 2023 17:09:51 +0200 Subject: [PATCH 78/94] Update `DisplayHtml` to use proper dark theme background color --- app/core/src/main/java/com/fsck/k9/message/html/DisplayHtml.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/core/src/main/java/com/fsck/k9/message/html/DisplayHtml.kt b/app/core/src/main/java/com/fsck/k9/message/html/DisplayHtml.kt index 9c009648a9..f1551b3aa2 100644 --- a/app/core/src/main/java/com/fsck/k9/message/html/DisplayHtml.kt +++ b/app/core/src/main/java/com/fsck/k9/message/html/DisplayHtml.kt @@ -27,8 +27,9 @@ class DisplayHtml(private val settings: HtmlSettings) : HtmlHeadProvider { private fun cssStyleTheme(): String { return if (settings.useDarkMode) { + // TODO: Don't hardcode these values. Inject them via HtmlSettings. " " } else { -- GitLab From 567a423e1015c1799c2a6704013d3661489c4864 Mon Sep 17 00:00:00 2001 From: cketti Date: Tue, 26 Sep 2023 17:46:26 +0200 Subject: [PATCH 79/94] Explicitly set background color in message view and compose screens --- .../main/java/com/fsck/k9/activity/MessageCompose.java | 10 +--------- app/ui/legacy/src/main/res/layout/message.xml | 5 +++++ .../src/main/res/layout/message_compose_content.xml | 5 +++++ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageCompose.java b/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageCompose.java index af860e40bf..0301414519 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageCompose.java +++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageCompose.java @@ -266,15 +266,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, LayoutInflater themedLayoutInflater = LayoutInflater.from(themeContext); contentContainer.setLayoutInflater(themedLayoutInflater); - - View contentView = contentContainer.inflate(); - - // background color needs to be forced - //TODO: Change themes to use appropriate background colors that don't need overriding. - TypedValue outValue = new TypedValue(); - themeContext.getTheme().resolveAttribute(android.R.attr.windowBackground, outValue, true); - - contentView.setBackgroundColor(outValue.data); + contentContainer.inflate(); initializeActionBar(); diff --git a/app/ui/legacy/src/main/res/layout/message.xml b/app/ui/legacy/src/main/res/layout/message.xml index 3d206d1b58..472800146a 100644 --- a/app/ui/legacy/src/main/res/layout/message.xml +++ b/app/ui/legacy/src/main/res/layout/message.xml @@ -1,4 +1,8 @@ + + -- GitLab From b44d18082af4851db8354d3690f41250c900fa89 Mon Sep 17 00:00:00 2001 From: cketti Date: Tue, 26 Sep 2023 13:18:16 +0200 Subject: [PATCH 80/94] Use vector drawable for app icon Remove shadows (using blur) from the logo. This allows us to use a vector drawable as app icon. --- app/k9mail/src/debug/res/mipmap-hdpi/icon.png | Bin 4341 -> 0 bytes app/k9mail/src/debug/res/mipmap-mdpi/icon.png | Bin 2499 -> 0 bytes .../src/debug/res/mipmap-xhdpi/icon.png | Bin 5752 -> 0 bytes .../src/debug/res/mipmap-xxhdpi/icon.png | Bin 9252 -> 0 bytes .../src/debug/res/mipmap-xxxhdpi/icon.png | Bin 13200 -> 0 bytes .../src/debug/res/values/app_logo_colors.xml | 8 + .../fsck/k9/activity/LauncherShortcuts.java | 2 +- .../ic_launcher.xml | 6 +- .../src/main/res/drawable/ic_app_logo.xml | 150 +++++++++++++++ .../src/main/res/layout/fragment_about.xml | 2 +- .../legacy/src/main/res/mipmap-hdpi/icon.png | Bin 4295 -> 0 bytes .../legacy/src/main/res/mipmap-mdpi/icon.png | Bin 2427 -> 0 bytes .../legacy/src/main/res/mipmap-xhdpi/icon.png | Bin 5519 -> 0 bytes .../src/main/res/mipmap-xxhdpi/icon.png | Bin 8906 -> 0 bytes .../src/main/res/mipmap-xxxhdpi/icon.png | Bin 12668 -> 0 bytes .../src/main/res/values-v26/drawables.xml | 4 - .../src/main/res/values/app_logo_colors.xml | 8 + app/ui/legacy/src/main/res/values/colors.xml | 2 - .../legacy/src/main/res/values/drawables.xml | 2 +- images/K-9_Mail-no-shadows-debug.svg | 180 ++++++++++++++++++ images/K-9_Mail-no-shadows.svg | 180 ++++++++++++++++++ 21 files changed, 532 insertions(+), 12 deletions(-) delete mode 100644 app/k9mail/src/debug/res/mipmap-hdpi/icon.png delete mode 100644 app/k9mail/src/debug/res/mipmap-mdpi/icon.png delete mode 100644 app/k9mail/src/debug/res/mipmap-xhdpi/icon.png delete mode 100644 app/k9mail/src/debug/res/mipmap-xxhdpi/icon.png delete mode 100644 app/k9mail/src/debug/res/mipmap-xxxhdpi/icon.png create mode 100644 app/k9mail/src/debug/res/values/app_logo_colors.xml rename app/ui/legacy/src/main/res/{mipmap-anydpi-v26 => drawable-v26}/ic_launcher.xml (57%) create mode 100644 app/ui/legacy/src/main/res/drawable/ic_app_logo.xml delete mode 100644 app/ui/legacy/src/main/res/mipmap-hdpi/icon.png delete mode 100644 app/ui/legacy/src/main/res/mipmap-mdpi/icon.png delete mode 100644 app/ui/legacy/src/main/res/mipmap-xhdpi/icon.png delete mode 100644 app/ui/legacy/src/main/res/mipmap-xxhdpi/icon.png delete mode 100644 app/ui/legacy/src/main/res/mipmap-xxxhdpi/icon.png delete mode 100644 app/ui/legacy/src/main/res/values-v26/drawables.xml create mode 100644 app/ui/legacy/src/main/res/values/app_logo_colors.xml create mode 100644 images/K-9_Mail-no-shadows-debug.svg create mode 100644 images/K-9_Mail-no-shadows.svg diff --git a/app/k9mail/src/debug/res/mipmap-hdpi/icon.png b/app/k9mail/src/debug/res/mipmap-hdpi/icon.png deleted file mode 100644 index 67b558087e0bc3fc01dc8c80943e6e57800ff2a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4341 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 N002ovPDHLkV1hw-u?GME diff --git a/app/k9mail/src/debug/res/mipmap-xhdpi/icon.png b/app/k9mail/src/debug/res/mipmap-xhdpi/icon.png deleted file mode 100644 index 1157ecf00a6960df18a3635d10ec0877bbb74b1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5752 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 + + #5917ff + #7a45ff + #531ad8 + + #e3d9ff + diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/LauncherShortcuts.java b/app/ui/legacy/src/main/java/com/fsck/k9/activity/LauncherShortcuts.java index 3d2775b1fe..8d8d4a174e 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/LauncherShortcuts.java +++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/LauncherShortcuts.java @@ -41,7 +41,7 @@ public class LauncherShortcuts extends AccountList { displayName = account.getEmail(); } intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, displayName); - Parcelable iconResource = Intent.ShortcutIconResource.fromContext(this, R.mipmap.icon); + Parcelable iconResource = Intent.ShortcutIconResource.fromContext(this, R.drawable.ic_launcher); intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource); setResult(RESULT_OK, intent); diff --git a/app/ui/legacy/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/ui/legacy/src/main/res/drawable-v26/ic_launcher.xml similarity index 57% rename from app/ui/legacy/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to app/ui/legacy/src/main/res/drawable-v26/ic_launcher.xml index df4ae3c1a3..0ffce35477 100644 --- a/app/ui/legacy/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/ui/legacy/src/main/res/drawable-v26/ic_launcher.xml @@ -1,8 +1,8 @@ - + - + - \ No newline at end of file + diff --git a/app/ui/legacy/src/main/res/drawable/ic_app_logo.xml b/app/ui/legacy/src/main/res/drawable/ic_app_logo.xml new file mode 100644 index 0000000000..2977664bf8 --- /dev/null +++ b/app/ui/legacy/src/main/res/drawable/ic_app_logo.xml @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/ui/legacy/src/main/res/layout/fragment_about.xml b/app/ui/legacy/src/main/res/layout/fragment_about.xml index d69c7e5873..8292c82dd0 100644 --- a/app/ui/legacy/src/main/res/layout/fragment_about.xml +++ b/app/ui/legacy/src/main/res/layout/fragment_about.xml @@ -17,7 +17,7 @@ android:layout_gravity="center" android:layout_margin="16dp" android:contentDescription="@null" - app:srcCompat="@mipmap/icon" /> + app:srcCompat="@drawable/ic_app_logo" /> GLlm|=wB4GIM16+zJ~CW1j-MI`8k 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 diff --git a/app/ui/legacy/src/main/res/mipmap-mdpi/icon.png b/app/ui/legacy/src/main/res/mipmap-mdpi/icon.png deleted file mode 100644 index 9f34a43d59f7d26381401bcd2886b7cc8d9ae809..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2427 zcmV->3552EP)3}vK~!jg#hPi5RmBy@f8FoBfnf-%MwW7ctdt5N8i__+5)}|o z%cWFEG|@6Krc6>^KGo_Q7K_em~FhEo$AhHb1!ps0O z@6BEM2v@8b55V`*Y_#LE~?5i`5)S-X(%Zg$O5@=Ty(62 z%>_Kb{1`8%Z-hV zlUIn6EFxtNBA}F4$mh5I@H-FRTgAq>2q<7;CO2VO-f>D}LV3? z7~k_yx{~)05x1rd<9oVjBN!C3;Tu!aMpSg2dIGq8Cr|#(cOBpNTzt>Pa~(X_!S`Hz z*Y*2O9BU<*gf`C!;P#$8+3LEk@47Co>y(=3x_GYZ51j0NrHYM|jHL=q1kM4b0~rGH zlWx5Au6BTy7n+v<$AMmg{HZ6LtXPYb1_f0p+OO<7RM$b$*;2Ia8~^l(@4vdCZ{Pi2?|Q2*Ny0{;VPNU~ z&C`s!MI^D(MD7Jpkr$_lMe4f^sHE*wA`Z}>W79crJbO3bM8VopXhM_EHBoQb3{nfc zNL`VL+ELiA5t!o2b-;uq0b3Qy=1|j$FEFb=ga6QK)Ql;1z{I0e@_a(#m0wx=OZKNv z!F=@&%x%|}%4-fa4U5BV5m18pB>Yc;r^_x+<4_GTz z$Y2ZvKK1#2>*PvQBD45o$V01dc4WXa;3;Lz);CfcVN$&&beb3cLKtcjG;4$#g`%DJ2YzgMR70A>k^tL_dC$^$o z53^<&X897xkD`9xLgx847zr%>d@)qp1#I3@9oTGA1fz$XF67CeiSY7$V!PPuv{B6Eerb~sR~45|uXRU!9_ zQu9Z>ghr{5E+o7jY$f7pQw_W%Q!M@h`*lPrR3V=ttjb#o70cO5;A-EO=S$W3A@-9- zTLdI8W~dVIq{qws;{{*psHm$%7!eu3vK-h5ct@T5YsH_0Vhmyo7zwID2)6hfV*<}b zTcS^__r&z0<5j{IBE07g|DE7uA|@FN0S=9x=~&!2{gO;ZpR1J0c?vuwrRHLA5j+G} zm79aH_oePB>tJH~(R&ABSoy;Tz2Vos(ZBnfhn##b!4XS2Iu`tj@&VMmm1`dS-K1&L z=aj;1&#jcHaa>Iz>EFKl`~mHB-xP=$MXsY_H?WR_5!D=aIjVBWKIZ9$cFZIyxw~Lf=i#e z=;N0>99`P&gDjD#hYaaR^}he!GkdqUw*W&}a=$3nIgljM)!EVc;YEwDZ=C#r^H2(v zXaPcnQaaubXl>Jr_K~tTc&caj=Er{WC_&m(1YZvU2o7C6r{Er#JO3lMWOKO*QBPG% zA*JGd>3Nb01dq+vuZR?>zBF%ZtAyI7qJfovhkEDJc!WoVy=g_owL}oV_>+Ji2{2*!dQN z{k@2U$1O@T^_-c^zxc9rzEfV%26|3(H2?eucLK+#^BY0EA2Qr$q!~ z3?c@^1YQkW--%;5g*@))D9-38P9aa<@#C0;o)HsxUIZtfKeKb&%ikk7Zm;_T$5;pm zFw(Vq=Uayk?EkeW5v9XKFP=`QAP&a&;{!!7#t--Ak;#lEn8nE9f4=kh!Ci0eppLvB zF98Tv!J*dXr+?9RqI*YlYam9zl(!hg2pKWKaaVNvArfK?T3>hfj@FG&{fwYw`qcm= zrQS$7{f-N)aYIcv_MY(s9Qh-8iN37W_8LkF=<=2;h9g!n!tY@X{D277vTw!g6P zYa?fe-p8`i){?PI;;3k#iQt>rRDuPuXiHuE>8sl_I@3^877=_gqx)aqc1;AJ5Y+e~ zf_h*4PBtbP(`VL*7+{#-LtGE>U!JNkGThcQdCCn^go&bXcDN0AJ3*kh;@ADxf~1Tm zg^D7SKfbvHUrrpr@kWNXXB(R?1!nrb?~IO&yxx1b>k-Fsx+8jS*nGyAHc=UG3e^$~ t%m!wJ_ooOphvV|{|5GacD*cbizX1Jm>CK}5UPS-^002ovPDHLkV1fnSqW%B? diff --git a/app/ui/legacy/src/main/res/mipmap-xhdpi/icon.png b/app/ui/legacy/src/main/res/mipmap-xhdpi/icon.png deleted file mode 100644 index 206a05b53ca987379438bbb09f398432ac17e8bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5519 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 Rv=RUS002ovPDHLkV1nI?Q^x=R diff --git a/app/ui/legacy/src/main/res/mipmap-xxhdpi/icon.png b/app/ui/legacy/src/main/res/mipmap-xxhdpi/icon.png deleted file mode 100644 index cd3e89be8f2c5591e594e0c0cbe5863103bcdb60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8906 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 - - @mipmap/ic_launcher - diff --git a/app/ui/legacy/src/main/res/values/app_logo_colors.xml b/app/ui/legacy/src/main/res/values/app_logo_colors.xml new file mode 100644 index 0000000000..9642c4fa2f --- /dev/null +++ b/app/ui/legacy/src/main/res/values/app_logo_colors.xml @@ -0,0 +1,8 @@ + + + #ff1744 + #ff4569 + #d81a3d + + #ffdae1 + diff --git a/app/ui/legacy/src/main/res/values/colors.xml b/app/ui/legacy/src/main/res/values/colors.xml index d9acb45a68..1c2b159950 100644 --- a/app/ui/legacy/src/main/res/values/colors.xml +++ b/app/ui/legacy/src/main/res/values/colors.xml @@ -1,7 +1,5 @@ - #FFDAE1 - #444444 #888 diff --git a/app/ui/legacy/src/main/res/values/drawables.xml b/app/ui/legacy/src/main/res/values/drawables.xml index e5a393bafd..f5a91e6d53 100644 --- a/app/ui/legacy/src/main/res/values/drawables.xml +++ b/app/ui/legacy/src/main/res/values/drawables.xml @@ -1,4 +1,4 @@ - @mipmap/icon + @drawable/ic_app_logo diff --git a/images/K-9_Mail-no-shadows-debug.svg b/images/K-9_Mail-no-shadows-debug.svg new file mode 100644 index 0000000000..3468f33205 --- /dev/null +++ b/images/K-9_Mail-no-shadows-debug.svg @@ -0,0 +1,180 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/K-9_Mail-no-shadows.svg b/images/K-9_Mail-no-shadows.svg new file mode 100644 index 0000000000..11d59a4441 --- /dev/null +++ b/images/K-9_Mail-no-shadows.svg @@ -0,0 +1,180 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + -- GitLab From 3fcd472cb0c5c3690a50a3a444feac49cb89c168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 6 Sep 2023 15:18:33 +0200 Subject: [PATCH 81/94] Add EditIncomingServerSettingsViewModel and EditOutgoingServerSettingsViewModel --- feature/account/edit/build.gradle.kts | 4 + .../feature/account/edit/AccountEditModule.kt | 45 +++++- .../edit/domain/AccountEditDomainContract.kt | 13 ++ .../edit/domain/usecase/LoadAccountState.kt | 41 +++++ .../ui/EditIncomingServerSettingsViewModel.kt | 32 ++++ .../ui/EditOutgoingServerSettingsViewModel.kt | 31 ++++ .../account/edit/AccountEditModuleKtTest.kt | 70 +++++++++ .../domain/usecase/LoadAccountStateTest.kt | 145 ++++++++++++++++++ ...EditIncomingServerSettingsViewModelTest.kt | 78 ++++++++++ ...EditOutgoingServerSettingsViewModelTest.kt | 77 ++++++++++ .../server/settings/ServerConfigModule.kt | 2 +- .../IncomingServerSettingsStateMapper.kt | 2 +- .../IncomingServerSettingsViewModel.kt | 5 +- .../OutgoingServerSettingsStateMapper.kt | 2 +- .../OutgoingServerSettingsViewModel.kt | 4 +- .../account/setup/AccountSetupModule.kt | 4 +- 16 files changed, 542 insertions(+), 13 deletions(-) create mode 100644 feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/AccountEditDomainContract.kt create mode 100644 feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountState.kt create mode 100644 feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsViewModel.kt create mode 100644 feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsViewModel.kt create mode 100644 feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/AccountEditModuleKtTest.kt create mode 100644 feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountStateTest.kt create mode 100644 feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsViewModelTest.kt create mode 100644 feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsViewModelTest.kt diff --git a/feature/account/edit/build.gradle.kts b/feature/account/edit/build.gradle.kts index 3542be5267..5ef5291d04 100644 --- a/feature/account/edit/build.gradle.kts +++ b/feature/account/edit/build.gradle.kts @@ -20,8 +20,12 @@ dependencies { implementation(projects.core.ui.compose.designsystem) implementation(projects.core.common) + implementation(projects.mail.common) + implementation(projects.feature.account.common) implementation(projects.feature.account.oauth) + implementation(projects.feature.account.server.settings) + implementation(projects.feature.account.server.certificate) implementation(projects.feature.account.server.validation) testImplementation(projects.core.ui.compose.testing) diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt index 03413ba6c4..1097d58bab 100644 --- a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt @@ -1,9 +1,48 @@ package app.k9mail.feature.account.edit -import app.k9mail.core.common.coreCommonModule +import app.k9mail.feature.account.common.featureAccountCommonModule +import app.k9mail.feature.account.edit.domain.AccountEditDomainContract +import app.k9mail.feature.account.edit.domain.usecase.LoadAccountState +import app.k9mail.feature.account.edit.ui.EditIncomingServerSettingsViewModel +import app.k9mail.feature.account.edit.ui.EditOutgoingServerSettingsViewModel import app.k9mail.feature.account.oauth.featureAccountOAuthModule +import app.k9mail.feature.account.server.certificate.featureAccountServerCertificateModule +import app.k9mail.feature.account.server.settings.featureAccountServerSettingsModule +import app.k9mail.feature.account.server.validation.featureAccountServerValidationModule +import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module -val accountEditModule = module { - includes(coreCommonModule, featureAccountOAuthModule) +val featureAccountEditModule = module { + includes( + featureAccountCommonModule, + featureAccountOAuthModule, + featureAccountServerCertificateModule, + featureAccountServerSettingsModule, + featureAccountServerValidationModule, + ) + + factory { + LoadAccountState( + accountLoader = get(), + accountStateRepository = get(), + ) + } + + viewModel { (accountUuid: String) -> + EditIncomingServerSettingsViewModel( + accountUuid = accountUuid, + accountStateLoader = get(), + validator = get(), + accountStateRepository = get(), + ) + } + + viewModel { (accountUuid: String) -> + EditOutgoingServerSettingsViewModel( + accountUuid = accountUuid, + accountStateLoader = get(), + validator = get(), + accountStateRepository = get(), + ) + } } diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/AccountEditDomainContract.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/AccountEditDomainContract.kt new file mode 100644 index 0000000000..58dd693013 --- /dev/null +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/AccountEditDomainContract.kt @@ -0,0 +1,13 @@ +package app.k9mail.feature.account.edit.domain + +import app.k9mail.feature.account.common.domain.entity.AccountState + +interface AccountEditDomainContract { + + interface UseCase { + + fun interface LoadAccountState { + suspend fun execute(accountUuid: String): AccountState + } + } +} diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountState.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountState.kt new file mode 100644 index 0000000000..ea0676ca28 --- /dev/null +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountState.kt @@ -0,0 +1,41 @@ +package app.k9mail.feature.account.edit.domain.usecase + +import app.k9mail.feature.account.common.AccountCommonExternalContract +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.common.domain.entity.Account +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState +import app.k9mail.feature.account.edit.domain.AccountEditDomainContract + +class LoadAccountState( + private val accountLoader: AccountCommonExternalContract.AccountLoader, + private val accountStateRepository: AccountDomainContract.AccountStateRepository, +) : AccountEditDomainContract.UseCase.LoadAccountState { + override suspend fun execute(accountUuid: String): AccountState { + val accountState = accountStateRepository.getState() + return if (accountState.uuid == accountUuid) { + accountState + } else { + loadState(accountUuid) + } + } + + private suspend fun loadState(accountUuid: String): AccountState { + val account = accountLoader.loadAccount(accountUuid) + return if (account != null) { + val accountState = account.mapToAccountState() + accountState + } else { + AccountState(uuid = accountUuid) + }.also { accountStateRepository.setState(it) } + } + + private fun Account.mapToAccountState() = AccountState( + uuid = uuid, + emailAddress = emailAddress, + incomingServerSettings = incomingServerSettings, + outgoingServerSettings = outgoingServerSettings, + authorizationState = AuthorizationState(authorizationState), + options = options, + ) +} diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsViewModel.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsViewModel.kt new file mode 100644 index 0000000000..23a04c604a --- /dev/null +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsViewModel.kt @@ -0,0 +1,32 @@ +package app.k9mail.feature.account.edit.ui + +import androidx.lifecycle.viewModelScope +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.edit.domain.AccountEditDomainContract +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsViewModel +import app.k9mail.feature.account.server.settings.ui.incoming.toIncomingConfigState +import kotlinx.coroutines.launch + +class EditIncomingServerSettingsViewModel( + val accountUuid: String, + private val accountStateLoader: AccountEditDomainContract.UseCase.LoadAccountState, + validator: IncomingServerSettingsContract.Validator, + accountStateRepository: AccountDomainContract.AccountStateRepository, + initialState: IncomingServerSettingsContract.State = IncomingServerSettingsContract.State(), +) : IncomingServerSettingsViewModel( + validator = validator, + accountStateRepository = accountStateRepository, + initialState = initialState, +) { + + override fun loadAccountState() { + viewModelScope.launch { + val state = accountStateLoader.execute(accountUuid) + + updateState { + state.toIncomingConfigState() + } + } + } +} diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsViewModel.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsViewModel.kt new file mode 100644 index 0000000000..67453cbe0d --- /dev/null +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsViewModel.kt @@ -0,0 +1,31 @@ +package app.k9mail.feature.account.edit.ui + +import androidx.lifecycle.viewModelScope +import app.k9mail.feature.account.common.domain.AccountDomainContract +import app.k9mail.feature.account.edit.domain.AccountEditDomainContract +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsViewModel +import app.k9mail.feature.account.server.settings.ui.outgoing.toOutgoingConfigState +import kotlinx.coroutines.launch + +class EditOutgoingServerSettingsViewModel( + val accountUuid: String, + private val accountStateLoader: AccountEditDomainContract.UseCase.LoadAccountState, + validator: OutgoingServerSettingsContract.Validator, + accountStateRepository: AccountDomainContract.AccountStateRepository, + initialState: OutgoingServerSettingsContract.State = OutgoingServerSettingsContract.State(), +) : OutgoingServerSettingsViewModel( + validator = validator, + accountStateRepository = accountStateRepository, + initialState = initialState, +) { + override fun loadAccountState() { + viewModelScope.launch { + val state = accountStateLoader.execute(accountUuid) + + updateState { + state.toOutgoingConfigState() + } + } + } +} diff --git a/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/AccountEditModuleKtTest.kt b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/AccountEditModuleKtTest.kt new file mode 100644 index 0000000000..27ae9b1755 --- /dev/null +++ b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/AccountEditModuleKtTest.kt @@ -0,0 +1,70 @@ +package app.k9mail.feature.account.edit + +import android.content.Context +import app.k9mail.core.common.oauth.OAuthConfigurationFactory +import app.k9mail.feature.account.common.AccountCommonExternalContract +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.server.certificate.ui.ServerCertificateErrorContract +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract +import app.k9mail.feature.account.server.validation.ui.ServerValidationContract +import com.fsck.k9.mail.oauth.OAuth2TokenProvider +import com.fsck.k9.mail.oauth.OAuth2TokenProviderFactory +import com.fsck.k9.mail.ssl.LocalKeyStore +import com.fsck.k9.mail.ssl.TrustedSocketFactory +import org.junit.Test +import org.junit.runner.RunWith +import org.koin.android.ext.koin.androidContext +import org.koin.core.annotation.KoinExperimentalAPI +import org.koin.core.module.Module +import org.koin.dsl.koinApplication +import org.koin.dsl.module +import org.koin.test.KoinTest +import org.koin.test.check.checkModules +import org.koin.test.verify.verify +import org.mockito.Mockito +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment + +@OptIn(KoinExperimentalAPI::class) +@RunWith(RobolectricTestRunner::class) +class AccountEditModuleKtTest : KoinTest { + + private val externalModule: Module = module { + single { Mockito.mock() } + single { Mockito.mock() } + single { + TrustedSocketFactory { _, _, _, _ -> null } + } + single { OAuthConfigurationFactory { emptyMap() } } + single { + OAuth2TokenProviderFactory { _ -> + object : OAuth2TokenProvider { + override fun getToken(timeoutMillis: Long) = TODO() + override fun invalidateToken() = TODO() + } + } + } + } + + @Test + fun `should have a valid di module`() { + featureAccountEditModule.verify( + extraTypes = listOf( + Context::class, + AccountState::class, + Class.forName("net.openid.appauth.AppAuthConfiguration").kotlin, + ServerValidationContract.State::class, + ServerCertificateErrorContract.State::class, + IncomingServerSettingsContract.State::class, + OutgoingServerSettingsContract.State::class, + ), + ) + + koinApplication { + modules(externalModule, featureAccountEditModule) + androidContext(RuntimeEnvironment.getApplication()) + checkModules() + } + } +} diff --git a/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountStateTest.kt b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountStateTest.kt new file mode 100644 index 0000000000..b73953b5c9 --- /dev/null +++ b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountStateTest.kt @@ -0,0 +1,145 @@ +package app.k9mail.feature.account.edit.domain.usecase + +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.entity.Account +import app.k9mail.feature.account.common.domain.entity.AccountOptions +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthorizationState +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity +import assertk.assertThat +import assertk.assertions.isEqualTo +import com.fsck.k9.mail.AuthType +import com.fsck.k9.mail.ServerSettings +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class LoadAccountStateTest { + + @Test + fun `should load account state WHEN account in state repository has different UUID`() = runTest { + val testSubject = LoadAccountState( + accountLoader = { accountUuid -> + Account( + uuid = accountUuid, + emailAddress = EMAIL_ADDRESS, + incomingServerSettings = INCOMING_SERVER_SETTINGS, + outgoingServerSettings = OUTGOING_SERVER_SETTINGS, + authorizationState = AUTHORIZATION_STATE, + options = OPTIONS, + ) + }, + accountStateRepository = InMemoryAccountStateRepository(), + ) + + val result = testSubject.execute(ACCOUNT_UUID) + + assertThat(result).isEqualTo( + AccountState( + uuid = ACCOUNT_UUID, + emailAddress = EMAIL_ADDRESS, + incomingServerSettings = INCOMING_SERVER_SETTINGS, + outgoingServerSettings = OUTGOING_SERVER_SETTINGS, + authorizationState = AuthorizationState(AUTHORIZATION_STATE), + options = OPTIONS, + ), + ) + } + + @Test + fun `should return account state WHEN account in state repository has same UUID`() = runTest { + val testSubject = LoadAccountState( + accountLoader = { accountUuid -> + Account( + uuid = accountUuid, + emailAddress = EMAIL_ADDRESS, + incomingServerSettings = INCOMING_SERVER_SETTINGS, + outgoingServerSettings = OUTGOING_SERVER_SETTINGS, + authorizationState = AUTHORIZATION_STATE, + options = OPTIONS, + ) + }, + accountStateRepository = InMemoryAccountStateRepository().apply { + setState( + AccountState( + uuid = ACCOUNT_UUID, + emailAddress = EMAIL_ADDRESS, + incomingServerSettings = INCOMING_SERVER_SETTINGS, + outgoingServerSettings = OUTGOING_SERVER_SETTINGS, + authorizationState = AuthorizationState(AUTHORIZATION_STATE), + options = OPTIONS, + ), + ) + }, + ) + + val result = testSubject.execute(ACCOUNT_UUID) + + assertThat(result).isEqualTo( + AccountState( + uuid = ACCOUNT_UUID, + emailAddress = EMAIL_ADDRESS, + incomingServerSettings = INCOMING_SERVER_SETTINGS, + outgoingServerSettings = OUTGOING_SERVER_SETTINGS, + authorizationState = AuthorizationState(AUTHORIZATION_STATE), + options = OPTIONS, + ), + ) + } + + @Test + fun `should return empty account state WHEN account loader returns null`() = runTest { + val testSubject = LoadAccountState( + accountLoader = { null }, + accountStateRepository = InMemoryAccountStateRepository(), + ) + + val result = testSubject.execute(ACCOUNT_UUID) + + assertThat(result).isEqualTo( + AccountState( + uuid = ACCOUNT_UUID, + emailAddress = null, + incomingServerSettings = null, + outgoingServerSettings = null, + authorizationState = null, + options = null, + ), + ) + } + + private companion object { + const val ACCOUNT_UUID = "accountUuid" + const val EMAIL_ADDRESS = "test@example.com" + val INCOMING_SERVER_SETTINGS = ServerSettings( + type = "imap", + host = "imap.example.com", + port = 993, + connectionSecurity = MailConnectionSecurity.SSL_TLS_REQUIRED, + authenticationType = AuthType.PLAIN, + username = "user", + password = "password", + clientCertificateAlias = null, + ) + val OUTGOING_SERVER_SETTINGS = ServerSettings( + type = "smtp", + host = "smtp.example.com", + port = 465, + connectionSecurity = MailConnectionSecurity.SSL_TLS_REQUIRED, + authenticationType = AuthType.PLAIN, + username = "user", + password = "password", + clientCertificateAlias = null, + ) + + const val AUTHORIZATION_STATE = "authorization state" + + val OPTIONS = AccountOptions( + accountName = "accountName", + displayName = "displayName", + emailSignature = null, + checkFrequencyInMinutes = 15, + messageDisplayCount = 25, + showNotification = true, + ) + } +} diff --git a/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsViewModelTest.kt b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsViewModelTest.kt new file mode 100644 index 0000000000..be2c90395a --- /dev/null +++ b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsViewModelTest.kt @@ -0,0 +1,78 @@ +package app.k9mail.feature.account.edit.ui + +import app.k9mail.core.ui.compose.testing.MainDispatcherRule +import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed +import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.State +import app.k9mail.feature.account.server.settings.ui.incoming.fake.FakeIncomingServerSettingsValidator +import assertk.assertions.isEqualTo +import com.fsck.k9.mail.AuthType +import com.fsck.k9.mail.ServerSettings +import kotlinx.coroutines.delay +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class EditIncomingServerSettingsViewModelTest { + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @Test + fun `should load account state from use case`() = runTest { + val accountUuid = "accountUuid" + val accountState = AccountState( + uuid = "accountUuid", + emailAddress = "test@example.com", + incomingServerSettings = ServerSettings( + "imap", + "imap.example.com", + 123, + MailConnectionSecurity.SSL_TLS_REQUIRED, + AuthType.PLAIN, + "username", + "password", + clientCertificateAlias = null, + extra = emptyMap(), + ), + ) + + val testSubject = EditIncomingServerSettingsViewModel( + accountUuid = accountUuid, + accountStateLoader = { _ -> + delay(50) + accountState + }, + validator = FakeIncomingServerSettingsValidator(), + accountStateRepository = InMemoryAccountStateRepository(), + initialState = State(), + ) + val turbines = turbinesWithInitialStateCheck(testSubject, State()) + + testSubject.event(Event.LoadAccountState) + + assertThatAndMviTurbinesConsumed( + actual = turbines.awaitStateItem(), + turbines = turbines, + ) { + isEqualTo( + State( + server = StringInputField(value = "imap.example.com"), + security = ConnectionSecurity.TLS, + port = NumberInputField(value = 123L), + authenticationType = AuthenticationType.PasswordCleartext, + username = StringInputField(value = "username"), + password = StringInputField(value = "password"), + ), + ) + } + } +} diff --git a/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsViewModelTest.kt b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsViewModelTest.kt new file mode 100644 index 0000000000..2ebfd45d58 --- /dev/null +++ b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsViewModelTest.kt @@ -0,0 +1,77 @@ +package app.k9mail.feature.account.edit.ui + +import app.k9mail.core.ui.compose.testing.MainDispatcherRule +import app.k9mail.core.ui.compose.testing.mvi.assertThatAndMviTurbinesConsumed +import app.k9mail.core.ui.compose.testing.mvi.turbinesWithInitialStateCheck +import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository +import app.k9mail.feature.account.common.domain.entity.AccountState +import app.k9mail.feature.account.common.domain.entity.AuthenticationType +import app.k9mail.feature.account.common.domain.entity.ConnectionSecurity +import app.k9mail.feature.account.common.domain.entity.MailConnectionSecurity +import app.k9mail.feature.account.common.domain.input.NumberInputField +import app.k9mail.feature.account.common.domain.input.StringInputField +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Event +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State +import app.k9mail.feature.account.server.settings.ui.outgoing.fake.FakeOutgoingServerSettingsValidator +import assertk.assertions.isEqualTo +import com.fsck.k9.mail.AuthType +import com.fsck.k9.mail.ServerSettings +import kotlinx.coroutines.delay +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class EditOutgoingServerSettingsViewModelTest { + + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + + @Test + fun `should load account state from use case`() = runTest { + val accountUuid = "accountUuid" + val accountState = AccountState( + uuid = "accountUuid", + emailAddress = "test@example.com", + outgoingServerSettings = ServerSettings( + "smtp", + "smtp.example.com", + 123, + MailConnectionSecurity.SSL_TLS_REQUIRED, + AuthType.PLAIN, + "username", + "password", + clientCertificateAlias = null, + extra = emptyMap(), + ), + ) + val testSubject = EditOutgoingServerSettingsViewModel( + accountUuid = accountUuid, + accountStateLoader = { _ -> + delay(50) + accountState + }, + validator = FakeOutgoingServerSettingsValidator(), + accountStateRepository = InMemoryAccountStateRepository(), + initialState = State(), + ) + val turbines = turbinesWithInitialStateCheck(testSubject, State()) + + testSubject.event(Event.LoadAccountState) + + assertThatAndMviTurbinesConsumed( + actual = turbines.awaitStateItem(), + turbines = turbines, + ) { + isEqualTo( + State( + server = StringInputField(value = "smtp.example.com"), + security = ConnectionSecurity.TLS, + port = NumberInputField(value = 123L), + authenticationType = AuthenticationType.PasswordCleartext, + username = StringInputField(value = "username"), + password = StringInputField(value = "password"), + ), + ) + } + } +} diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt index 1af9721aa1..79002e6b6b 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt @@ -10,7 +10,7 @@ import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.core.module.Module import org.koin.dsl.module -val featureAccountServerConfigModule: Module = module { +val featureAccountServerSettingsModule: Module = module { factory { IncomingServerSettingsValidator() } factory { OutgoingServerSettingsValidator() } diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt index 89607a1d8a..2fef2862ae 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsStateMapper.kt @@ -12,7 +12,7 @@ import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSett import com.fsck.k9.mail.ServerSettings import com.fsck.k9.mail.store.imap.ImapStoreSettings -internal fun AccountState.toIncomingConfigState(): State { +fun AccountState.toIncomingConfigState(): State { val incomingServerSettings = incomingServerSettings return if (incomingServerSettings == null) { State( diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt index 4770a61f8a..22f814cd97 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/incoming/IncomingServerSettingsViewModel.kt @@ -12,9 +12,8 @@ import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSett import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.Validator import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsContract.ViewModel -class IncomingServerSettingsViewModel( +open class IncomingServerSettingsViewModel( private val validator: Validator, -// private val serverSettingsRepository: ServerConfigDomainContract.ServerSettingsRepository, private val accountStateRepository: AccountDomainContract.AccountStateRepository, initialState: State = State(), ) : BaseViewModel(initialState = initialState), ViewModel { @@ -51,7 +50,7 @@ class IncomingServerSettingsViewModel( } } - private fun loadAccountState() { + protected open fun loadAccountState() { updateState { accountStateRepository.getState().toIncomingConfigState() } diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt index 02093ac83d..8543f55962 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsStateMapper.kt @@ -10,7 +10,7 @@ import app.k9mail.feature.account.common.domain.input.StringInputField import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.State import com.fsck.k9.mail.ServerSettings -internal fun AccountState.toOutgoingConfigState(): State { +fun AccountState.toOutgoingConfigState(): State { val outgoingServerSettings = outgoingServerSettings return if (outgoingServerSettings == null) { State( diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt index 3c7c5b0881..34f3715989 100644 --- a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt +++ b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ui/outgoing/OutgoingServerSettingsViewModel.kt @@ -11,7 +11,7 @@ import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSett import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.Validator import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsContract.ViewModel -class OutgoingServerSettingsViewModel( +open class OutgoingServerSettingsViewModel( private val validator: Validator, private val accountStateRepository: AccountDomainContract.AccountStateRepository, initialState: State = State(), @@ -36,7 +36,7 @@ class OutgoingServerSettingsViewModel( } } - private fun loadAccountState() { + protected open fun loadAccountState() { updateState { accountStateRepository.getState().toOutgoingConfigState() } diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt index 6dba0571d8..6659bf885f 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/AccountSetupModule.kt @@ -4,7 +4,7 @@ import app.k9mail.autodiscovery.api.AutoDiscoveryService import app.k9mail.autodiscovery.service.RealAutoDiscoveryService import app.k9mail.feature.account.common.featureAccountCommonModule import app.k9mail.feature.account.oauth.featureAccountOAuthModule -import app.k9mail.feature.account.server.settings.featureAccountServerConfigModule +import app.k9mail.feature.account.server.settings.featureAccountServerSettingsModule import app.k9mail.feature.account.server.validation.featureAccountServerValidationModule import app.k9mail.feature.account.setup.domain.DomainContract import app.k9mail.feature.account.setup.domain.usecase.CreateAccount @@ -26,7 +26,7 @@ val featureAccountSetupModule: Module = module { featureAccountCommonModule, featureAccountOAuthModule, featureAccountServerValidationModule, - featureAccountServerConfigModule, + featureAccountServerSettingsModule, ) single { -- GitLab From 10cb49cbb47527ca53320d5d0c7e6c2d1aa3a5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 17:47:41 +0200 Subject: [PATCH 82/94] Add NavBackStackEntryExtension with getArgument method --- core/ui/compose/common/build.gradle.kts | 2 ++ .../common/navigation/NavBackStackEntryExtension.kt | 7 +++++++ 2 files changed, 9 insertions(+) create mode 100644 core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/navigation/NavBackStackEntryExtension.kt diff --git a/core/ui/compose/common/build.gradle.kts b/core/ui/compose/common/build.gradle.kts index d1b76a4dd5..88b78e4cd1 100644 --- a/core/ui/compose/common/build.gradle.kts +++ b/core/ui/compose/common/build.gradle.kts @@ -8,5 +8,7 @@ android { } dependencies { + implementation(libs.androidx.compose.activity) + testImplementation(projects.core.ui.compose.testing) } diff --git a/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/navigation/NavBackStackEntryExtension.kt b/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/navigation/NavBackStackEntryExtension.kt new file mode 100644 index 0000000000..c442548623 --- /dev/null +++ b/core/ui/compose/common/src/main/kotlin/app/k9mail/core/ui/compose/common/navigation/NavBackStackEntryExtension.kt @@ -0,0 +1,7 @@ +package app.k9mail.core.ui.compose.common.navigation + +import androidx.navigation.NavBackStackEntry + +fun NavBackStackEntry.getStringArgument(key: String): String { + return arguments?.getString(key) ?: error("Missing argument: $key") +} -- GitLab From dc142fea79d3c0ba450d788affdb255f90909822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 19 Sep 2023 10:59:36 +0200 Subject: [PATCH 83/94] Add NavHost for incoming and outgoing server settings editing --- .../edit/navigation/AccountEditNavigation.kt | 75 +++++++++++++++++++ .../ui/EditIncomingServerSettingsNavHost.kt | 52 +++++++++++++ .../ui/EditOutgoingServerSettingsNavHost.kt | 53 +++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/navigation/AccountEditNavigation.kt create mode 100644 feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsNavHost.kt create mode 100644 feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsNavHost.kt diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/navigation/AccountEditNavigation.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/navigation/AccountEditNavigation.kt new file mode 100644 index 0000000000..c16eebb41f --- /dev/null +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/navigation/AccountEditNavigation.kt @@ -0,0 +1,75 @@ +package app.k9mail.feature.account.edit.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavType +import androidx.navigation.compose.composable +import androidx.navigation.navArgument +import app.k9mail.core.ui.compose.common.navigation.getArgument +import app.k9mail.feature.account.edit.ui.EditIncomingServerSettingsNavHost +import app.k9mail.feature.account.edit.ui.EditOutgoingServerSettingsNavHost +import kotlinx.collections.immutable.ImmutableMap +import kotlinx.collections.immutable.persistentMapOf + +internal const val ARGUMENT_ACCOUNT_UUID = "accountUuid" + +const val NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_INCOMING = "/account/edit/config/incoming/{accountUuid}" +const val NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_OUTGOING = "/account/edit/config/outgoing/{accountUuid}" + +fun NavController.navigateToAccountEditConfigIncoming(accountUuid: String) { + navigate( + route = NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_INCOMING.withAccountUuid(accountUuid), + ) +} + +fun NavController.navigateToAccountEditConfigOutgoing(accountUuid: String) { + navigate( + route = NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_OUTGOING.withAccountUuid(accountUuid), + ) +} + +fun NavGraphBuilder.accountEditRoute( + startDestinationArguments: ImmutableMap = persistentMapOf(), + onBack: () -> Unit, + onFinish: () -> Unit, +) { + composable( + route = NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_INCOMING, + arguments = listOf( + navArgument(ARGUMENT_ACCOUNT_UUID) { + type = NavType.StringType + defaultValue = startDestinationArguments[ARGUMENT_ACCOUNT_UUID] ?: "" + }, + ), + ) { backStackEntry -> + val accountUuid = backStackEntry.getArgument(ARGUMENT_ACCOUNT_UUID) + EditIncomingServerSettingsNavHost( + accountUuid = accountUuid, + onFinish = { onFinish() }, + onBack = onBack, + ) + } + composable( + route = NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_OUTGOING, + arguments = listOf( + navArgument(ARGUMENT_ACCOUNT_UUID) { + type = NavType.StringType + defaultValue = startDestinationArguments[ARGUMENT_ACCOUNT_UUID] ?: "" + }, + ), + ) { backStackEntry -> + val accountUuid = backStackEntry.getArgument(ARGUMENT_ACCOUNT_UUID) + EditOutgoingServerSettingsNavHost( + accountUuid = accountUuid, + onFinish = { onFinish() }, + onBack = onBack, + ) + } +} + +fun String.withAccountUuid(accountUuid: String): String { + return replace( + oldValue = "{$ARGUMENT_ACCOUNT_UUID}", + newValue = accountUuid, + ) +} diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsNavHost.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsNavHost.kt new file mode 100644 index 0000000000..329fdceee9 --- /dev/null +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditIncomingServerSettingsNavHost.kt @@ -0,0 +1,52 @@ +package app.k9mail.feature.account.edit.ui + +import androidx.compose.runtime.Composable +import androidx.navigation.NavController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import app.k9mail.feature.account.server.settings.ui.incoming.IncomingServerSettingsScreen +import app.k9mail.feature.account.server.validation.ui.IncomingServerValidationViewModel +import app.k9mail.feature.account.server.validation.ui.ServerValidationScreen +import org.koin.androidx.compose.koinViewModel +import org.koin.core.parameter.parametersOf + +private const val NESTED_NAVIGATION_ROUTE_CONFIG = "config" +private const val NESTED_NAVIGATION_ROUTE_VALIDATION = "validation" + +private fun NavController.navigateToValidation() { + navigate(NESTED_NAVIGATION_ROUTE_VALIDATION) +} + +@Composable +fun EditIncomingServerSettingsNavHost( + accountUuid: String, + onFinish: () -> Unit, + onBack: () -> Unit, +) { + val navController = rememberNavController() + + NavHost( + navController = navController, + startDestination = NESTED_NAVIGATION_ROUTE_CONFIG, + ) { + composable(route = NESTED_NAVIGATION_ROUTE_CONFIG) { + IncomingServerSettingsScreen( + onBack = onBack, + onNext = { navController.navigateToValidation() }, + viewModel = koinViewModel { + parametersOf(accountUuid) + }, + ) + } + composable(route = NESTED_NAVIGATION_ROUTE_VALIDATION) { + ServerValidationScreen( + onBack = { navController.popBackStack() }, + onNext = onFinish, + viewModel = koinViewModel { + parametersOf(accountUuid) + }, + ) + } + } +} diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsNavHost.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsNavHost.kt new file mode 100644 index 0000000000..5b6d5ed5e7 --- /dev/null +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/ui/EditOutgoingServerSettingsNavHost.kt @@ -0,0 +1,53 @@ +package app.k9mail.feature.account.edit.ui + +import androidx.compose.runtime.Composable +import androidx.navigation.NavController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsScreen +import app.k9mail.feature.account.server.settings.ui.outgoing.OutgoingServerSettingsViewModel +import app.k9mail.feature.account.server.validation.ui.OutgoingServerValidationViewModel +import app.k9mail.feature.account.server.validation.ui.ServerValidationScreen +import org.koin.androidx.compose.koinViewModel +import org.koin.core.parameter.parametersOf + +private const val NESTED_NAVIGATION_ROUTE_CONFIG = "config" +private const val NESTED_NAVIGATION_ROUTE_VALIDATION = "validation" + +private fun NavController.navigateToValidation() { + navigate(NESTED_NAVIGATION_ROUTE_VALIDATION) +} + +@Composable +fun EditOutgoingServerSettingsNavHost( + accountUuid: String, + onFinish: () -> Unit, + onBack: () -> Unit, +) { + val navController = rememberNavController() + + NavHost( + navController = navController, + startDestination = NESTED_NAVIGATION_ROUTE_CONFIG, + ) { + composable(route = NESTED_NAVIGATION_ROUTE_CONFIG) { + OutgoingServerSettingsScreen( + onBack = onBack, + onNext = { navController.navigateToValidation() }, + viewModel = koinViewModel { + parametersOf(accountUuid) + }, + ) + } + composable(route = NESTED_NAVIGATION_ROUTE_VALIDATION) { + ServerValidationScreen( + onBack = { navController.popBackStack() }, + onNext = onFinish, + viewModel = koinViewModel { + parametersOf(accountUuid) + }, + ) + } + } +} -- GitLab From bdce4ce5c0c6270606c0eb92049c6075f07cd6f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Fri, 15 Sep 2023 17:40:03 +0200 Subject: [PATCH 84/94] Add account edit to feature launcher --- .../k9mail/feature/preview/FeatureModule.kt | 2 ++ .../preview/navigation/FeatureNavHost.kt | 8 ++++++++ feature/launcher/build.gradle.kts | 1 + .../launcher/FeatureLauncherActivity.kt | 19 +++++++++++++++++++ .../launcher/di/FeatureLauncherModule.kt | 2 ++ .../navigation/FeatureLauncherNavHost.kt | 12 ++++++++++++ .../feature/launcher/ui/FeatureLauncherApp.kt | 3 +++ 7 files changed, 47 insertions(+) diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt index 1a5676f0d3..a2b003825c 100644 --- a/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/FeatureModule.kt @@ -3,6 +3,7 @@ package app.k9mail.feature.preview import app.k9mail.core.common.oauth.OAuthConfigurationFactory import app.k9mail.feature.account.common.AccountCommonExternalContract import app.k9mail.feature.account.edit.AccountEditExternalContract +import app.k9mail.feature.account.edit.featureAccountEditModule import app.k9mail.feature.account.setup.AccountSetupExternalContract import app.k9mail.feature.account.setup.featureAccountSetupModule import app.k9mail.feature.preview.account.AccountOwnerNameProvider @@ -44,5 +45,6 @@ val featureModule: Module = module { includes( accountModule, featureAccountSetupModule, + featureAccountEditModule, ) } diff --git a/app-feature-preview/src/main/java/app/k9mail/feature/preview/navigation/FeatureNavHost.kt b/app-feature-preview/src/main/java/app/k9mail/feature/preview/navigation/FeatureNavHost.kt index d25543864c..73d1f22544 100644 --- a/app-feature-preview/src/main/java/app/k9mail/feature/preview/navigation/FeatureNavHost.kt +++ b/app-feature-preview/src/main/java/app/k9mail/feature/preview/navigation/FeatureNavHost.kt @@ -4,6 +4,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost +import app.k9mail.feature.account.edit.navigation.accountEditRoute +import app.k9mail.feature.account.edit.navigation.navigateToAccountEditConfigIncoming import app.k9mail.feature.account.setup.navigation.accountSetupRoute import app.k9mail.feature.account.setup.navigation.navigateToAccountSetup import app.k9mail.feature.onboarding.navigation.NAVIGATION_ROUTE_ONBOARDING @@ -26,6 +28,12 @@ fun FeatureNavHost( onImport = { /* TODO */ }, ) accountSetupRoute( + onBack = navController::popBackStack, + onFinish = { accountUuid -> + navController.navigateToAccountEditConfigIncoming(accountUuid) + }, + ) + accountEditRoute( onBack = navController::popBackStack, onFinish = { navController.navigateToOnboarding() }, ) diff --git a/feature/launcher/build.gradle.kts b/feature/launcher/build.gradle.kts index ed6f16361a..e28f2540e1 100644 --- a/feature/launcher/build.gradle.kts +++ b/feature/launcher/build.gradle.kts @@ -20,6 +20,7 @@ dependencies { implementation(projects.core.ui.compose.designsystem) implementation(projects.feature.onboarding) implementation(projects.feature.account.setup) + implementation(projects.feature.account.edit) testImplementation(projects.core.ui.compose.testing) } diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt index df0df6ca39..1804095a87 100644 --- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt +++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt @@ -10,6 +10,7 @@ import app.k9mail.core.ui.compose.common.navigation.toDeepLinkUri import app.k9mail.feature.account.setup.navigation.NAVIGATION_ROUTE_ACCOUNT_SETUP import app.k9mail.feature.launcher.ui.FeatureLauncherApp import app.k9mail.feature.onboarding.navigation.NAVIGATION_ROUTE_ONBOARDING +import kotlinx.collections.immutable.toImmutableMap class FeatureLauncherActivity : ComponentActivity() { @@ -40,5 +41,23 @@ class FeatureLauncherActivity : ComponentActivity() { } context.startActivity(intent) } + + @JvmStatic + fun launchEditIncomingSettings(context: Activity, accountUuid: String) { + val intent = Intent(context, FeatureLauncherActivity::class.java).apply { + putExtra(EXTRA_DESTINATION, DESTINATION_EDIT_ACCOUNT_INCOMING_CONFIG) + putExtra(EXTRA_ACCOUNT_UUID, accountUuid) + } + context.startActivity(intent) + } + + @JvmStatic + fun launchEditOutgoingSettings(context: Activity, accountUuid: String) { + val intent = Intent(context, FeatureLauncherActivity::class.java).apply { + putExtra(EXTRA_DESTINATION, DESTINATION_EDIT_ACCOUNT_OUTGOING_CONFIG) + putExtra(EXTRA_ACCOUNT_UUID, accountUuid) + } + context.startActivity(intent) + } } } diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/di/FeatureLauncherModule.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/di/FeatureLauncherModule.kt index 7cc641f17b..1e5a5e4735 100644 --- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/di/FeatureLauncherModule.kt +++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/di/FeatureLauncherModule.kt @@ -1,10 +1,12 @@ package app.k9mail.feature.launcher.di +import app.k9mail.feature.account.edit.featureAccountEditModule import app.k9mail.feature.account.setup.featureAccountSetupModule import org.koin.dsl.module val featureLauncherModule = module { includes( featureAccountSetupModule, + featureAccountEditModule, ) } diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt index 2faec3562e..a5762ed46f 100644 --- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt +++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt @@ -4,12 +4,16 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost +import app.k9mail.core.ui.compose.common.activity.LocalActivity +import app.k9mail.feature.account.edit.navigation.accountEditRoute import app.k9mail.feature.account.setup.navigation.accountSetupRoute import app.k9mail.feature.account.setup.navigation.navigateToAccountSetup import app.k9mail.feature.launcher.FeatureLauncherExternalContract.AccountSetupFinishedLauncher import app.k9mail.feature.launcher.FeatureLauncherExternalContract.ImportSettingsLauncher import app.k9mail.feature.onboarding.navigation.NAVIGATION_ROUTE_ONBOARDING import app.k9mail.feature.onboarding.navigation.onboardingRoute +import kotlinx.collections.immutable.ImmutableMap +import kotlinx.collections.immutable.persistentMapOf import org.koin.compose.koinInject @Composable @@ -17,9 +21,12 @@ fun FeatureLauncherNavHost( navController: NavHostController, onBack: () -> Unit, modifier: Modifier = Modifier, + startDestinationArguments: ImmutableMap = persistentMapOf(), importSettingsLauncher: ImportSettingsLauncher = koinInject(), accountSetupFinishedLauncher: AccountSetupFinishedLauncher = koinInject(), ) { + val activity = LocalActivity.current + NavHost( navController = navController, startDestination = NAVIGATION_ROUTE_ONBOARDING, @@ -33,5 +40,10 @@ fun FeatureLauncherNavHost( onBack = onBack, onFinish = { accountSetupFinishedLauncher.launch(it) }, ) + accountEditRoute( + startDestinationArguments = startDestinationArguments, + onBack = onBack, + onFinish = { activity.finish() }, + ) } } diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt index 27aef780a5..6d24197aca 100644 --- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt +++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt @@ -9,10 +9,13 @@ import app.k9mail.core.ui.compose.common.activity.LocalActivity import app.k9mail.core.ui.compose.designsystem.atom.Background import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.feature.launcher.navigation.FeatureLauncherNavHost +import kotlinx.collections.immutable.ImmutableMap +import kotlinx.collections.immutable.persistentMapOf @Composable fun FeatureLauncherApp( modifier: Modifier = Modifier, + startDestinationArguments: ImmutableMap = persistentMapOf(), ) { val navController = rememberNavController() -- GitLab From f980caa48ffaef4e1c51ee947027de4eab84520e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Wed, 13 Sep 2023 17:55:12 +0200 Subject: [PATCH 85/94] Add new_account_edit feature flag --- .../k9/featureflag/InMemoryFeatureFlagFactory.kt | 3 ++- .../ui/settings/account/AccountSettingsFragment.kt | 13 +++++++++++-- .../app/k9mail/core/featureflag/FeatureFlagKey.kt | 2 ++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/k9mail/src/main/java/com/fsck/k9/featureflag/InMemoryFeatureFlagFactory.kt b/app/k9mail/src/main/java/com/fsck/k9/featureflag/InMemoryFeatureFlagFactory.kt index 4d1a923cb9..da37d49036 100644 --- a/app/k9mail/src/main/java/com/fsck/k9/featureflag/InMemoryFeatureFlagFactory.kt +++ b/app/k9mail/src/main/java/com/fsck/k9/featureflag/InMemoryFeatureFlagFactory.kt @@ -2,11 +2,12 @@ package com.fsck.k9.featureflag import app.k9mail.core.featureflag.FeatureFlag import app.k9mail.core.featureflag.FeatureFlagFactory +import app.k9mail.core.featureflag.FeatureFlagKey class InMemoryFeatureFlagFactory : FeatureFlagFactory { override fun createFeatureCatalog(): List { return listOf( - // empty + FeatureFlag(FeatureFlagKey("new_account_edit"), false), ) } } diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/account/AccountSettingsFragment.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/account/AccountSettingsFragment.kt index fdc4d1ee52..dff2db9dcf 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/account/AccountSettingsFragment.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/settings/account/AccountSettingsFragment.kt @@ -13,6 +13,9 @@ import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.PreferenceCategory import androidx.preference.SwitchPreference +import app.k9mail.core.featureflag.FeatureFlagProvider +import app.k9mail.core.featureflag.toFeatureFlagKey +import app.k9mail.feature.launcher.FeatureLauncherActivity import com.fsck.k9.Account import com.fsck.k9.account.BackgroundAccountRemover import com.fsck.k9.activity.ManageIdentities @@ -52,6 +55,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), ConfirmationDialogFr private val notificationChannelManager: NotificationChannelManager by inject() private val notificationSettingsUpdater: NotificationSettingsUpdater by inject() private val vibrator: Vibrator by inject() + private val featureFlagProvider: FeatureFlagProvider by inject() private lateinit var dataStore: AccountSettingsDataStore @@ -123,13 +127,16 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), ConfirmationDialogFr onDeleteAccount() true } + else -> super.onOptionsItemSelected(item) } } private fun initializeIncomingServer() { findPreference(PREFERENCE_INCOMING_SERVER)?.onClick { - AccountSetupIncoming.actionEditIncomingSettings(requireActivity(), accountUuid) + featureFlagProvider.provide("new_account_edit".toFeatureFlagKey()) + .onEnabled { FeatureLauncherActivity.launchEditIncomingSettings(requireActivity(), accountUuid) } + .onDisabled { AccountSetupIncoming.actionEditIncomingSettings(requireActivity(), accountUuid) } } } @@ -155,7 +162,9 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), ConfirmationDialogFr private fun initializeOutgoingServer() { findPreference(PREFERENCE_OUTGOING_SERVER)?.onClick { - AccountSetupOutgoing.actionEditOutgoingSettings(requireActivity(), accountUuid) + featureFlagProvider.provide("new_account_edit".toFeatureFlagKey()) + .onEnabled { FeatureLauncherActivity.launchEditOutgoingSettings(requireActivity(), accountUuid) } + .onDisabled { AccountSetupOutgoing.actionEditOutgoingSettings(requireActivity(), accountUuid) } } } diff --git a/core/featureflags/src/main/kotlin/app/k9mail/core/featureflag/FeatureFlagKey.kt b/core/featureflags/src/main/kotlin/app/k9mail/core/featureflag/FeatureFlagKey.kt index d7901d229a..4e54b402d4 100644 --- a/core/featureflags/src/main/kotlin/app/k9mail/core/featureflag/FeatureFlagKey.kt +++ b/core/featureflags/src/main/kotlin/app/k9mail/core/featureflag/FeatureFlagKey.kt @@ -2,3 +2,5 @@ package app.k9mail.core.featureflag @JvmInline value class FeatureFlagKey(val key: String) + +fun String.toFeatureFlagKey(): FeatureFlagKey = FeatureFlagKey(this) -- GitLab From d6d8be95ba6019c88f7fc293f4228fd18c66bd23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 26 Sep 2023 16:18:13 +0200 Subject: [PATCH 86/94] Rename ServerConfigModule to ServerSettingsModule --- .../settings/{ServerConfigModule.kt => ServerSettingsModule.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/{ServerConfigModule.kt => ServerSettingsModule.kt} (100%) diff --git a/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt b/feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerSettingsModule.kt similarity index 100% rename from feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerConfigModule.kt rename to feature/account/server/settings/src/main/kotlin/app/k9mail/feature/account/server/settings/ServerSettingsModule.kt -- GitLab From 2f9f757e60972a04fadda9fd3165a129cea328d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 26 Sep 2023 16:20:24 +0200 Subject: [PATCH 87/94] Change to deep link navigation --- .../edit/navigation/AccountEditNavigation.kt | 21 +++++++------------ .../navigation/AccountSetupNavigation.kt | 2 +- .../launcher/FeatureLauncherActivity.kt | 10 ++++----- .../navigation/FeatureLauncherNavHost.kt | 4 ---- .../feature/launcher/ui/FeatureLauncherApp.kt | 3 --- .../navigation/OnboardingNavigation.kt | 2 +- 6 files changed, 15 insertions(+), 27 deletions(-) diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/navigation/AccountEditNavigation.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/navigation/AccountEditNavigation.kt index c16eebb41f..2692bd103f 100644 --- a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/navigation/AccountEditNavigation.kt +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/navigation/AccountEditNavigation.kt @@ -3,18 +3,16 @@ package app.k9mail.feature.account.edit.navigation import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavType -import androidx.navigation.compose.composable import androidx.navigation.navArgument -import app.k9mail.core.ui.compose.common.navigation.getArgument +import app.k9mail.core.ui.compose.common.navigation.deepLinkComposable +import app.k9mail.core.ui.compose.common.navigation.getStringArgument import app.k9mail.feature.account.edit.ui.EditIncomingServerSettingsNavHost import app.k9mail.feature.account.edit.ui.EditOutgoingServerSettingsNavHost -import kotlinx.collections.immutable.ImmutableMap -import kotlinx.collections.immutable.persistentMapOf internal const val ARGUMENT_ACCOUNT_UUID = "accountUuid" -const val NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_INCOMING = "/account/edit/config/incoming/{accountUuid}" -const val NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_OUTGOING = "/account/edit/config/outgoing/{accountUuid}" +const val NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_INCOMING = "account/edit/config/incoming/{accountUuid}" +const val NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_OUTGOING = "account/edit/config/outgoing/{accountUuid}" fun NavController.navigateToAccountEditConfigIncoming(accountUuid: String) { navigate( @@ -29,36 +27,33 @@ fun NavController.navigateToAccountEditConfigOutgoing(accountUuid: String) { } fun NavGraphBuilder.accountEditRoute( - startDestinationArguments: ImmutableMap = persistentMapOf(), onBack: () -> Unit, onFinish: () -> Unit, ) { - composable( + deepLinkComposable( route = NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_INCOMING, arguments = listOf( navArgument(ARGUMENT_ACCOUNT_UUID) { type = NavType.StringType - defaultValue = startDestinationArguments[ARGUMENT_ACCOUNT_UUID] ?: "" }, ), ) { backStackEntry -> - val accountUuid = backStackEntry.getArgument(ARGUMENT_ACCOUNT_UUID) + val accountUuid = backStackEntry.getStringArgument(ARGUMENT_ACCOUNT_UUID) EditIncomingServerSettingsNavHost( accountUuid = accountUuid, onFinish = { onFinish() }, onBack = onBack, ) } - composable( + deepLinkComposable( route = NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_OUTGOING, arguments = listOf( navArgument(ARGUMENT_ACCOUNT_UUID) { type = NavType.StringType - defaultValue = startDestinationArguments[ARGUMENT_ACCOUNT_UUID] ?: "" }, ), ) { backStackEntry -> - val accountUuid = backStackEntry.getArgument(ARGUMENT_ACCOUNT_UUID) + val accountUuid = backStackEntry.getStringArgument(ARGUMENT_ACCOUNT_UUID) EditOutgoingServerSettingsNavHost( accountUuid = accountUuid, onFinish = { onFinish() }, diff --git a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt index f2565b783f..5d4eb2ce88 100644 --- a/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt +++ b/feature/account/setup/src/main/kotlin/app/k9mail/feature/account/setup/navigation/AccountSetupNavigation.kt @@ -6,7 +6,7 @@ import androidx.navigation.NavOptions import app.k9mail.core.ui.compose.common.navigation.deepLinkComposable import app.k9mail.feature.account.setup.ui.AccountSetupScreen -const val NAVIGATION_ROUTE_ACCOUNT_SETUP = "/account/setup" +const val NAVIGATION_ROUTE_ACCOUNT_SETUP = "account/setup" fun NavController.navigateToAccountSetup(navOptions: NavOptions? = null) { navigate(NAVIGATION_ROUTE_ACCOUNT_SETUP, navOptions) diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt index 1804095a87..485bb83a68 100644 --- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt +++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/FeatureLauncherActivity.kt @@ -7,10 +7,12 @@ import androidx.activity.ComponentActivity import androidx.core.view.WindowCompat import app.k9mail.core.ui.compose.common.activity.setActivityContent import app.k9mail.core.ui.compose.common.navigation.toDeepLinkUri +import app.k9mail.feature.account.edit.navigation.NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_INCOMING +import app.k9mail.feature.account.edit.navigation.NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_OUTGOING +import app.k9mail.feature.account.edit.navigation.withAccountUuid import app.k9mail.feature.account.setup.navigation.NAVIGATION_ROUTE_ACCOUNT_SETUP import app.k9mail.feature.launcher.ui.FeatureLauncherApp import app.k9mail.feature.onboarding.navigation.NAVIGATION_ROUTE_ONBOARDING -import kotlinx.collections.immutable.toImmutableMap class FeatureLauncherActivity : ComponentActivity() { @@ -45,8 +47,7 @@ class FeatureLauncherActivity : ComponentActivity() { @JvmStatic fun launchEditIncomingSettings(context: Activity, accountUuid: String) { val intent = Intent(context, FeatureLauncherActivity::class.java).apply { - putExtra(EXTRA_DESTINATION, DESTINATION_EDIT_ACCOUNT_INCOMING_CONFIG) - putExtra(EXTRA_ACCOUNT_UUID, accountUuid) + data = NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_INCOMING.withAccountUuid(accountUuid).toDeepLinkUri() } context.startActivity(intent) } @@ -54,8 +55,7 @@ class FeatureLauncherActivity : ComponentActivity() { @JvmStatic fun launchEditOutgoingSettings(context: Activity, accountUuid: String) { val intent = Intent(context, FeatureLauncherActivity::class.java).apply { - putExtra(EXTRA_DESTINATION, DESTINATION_EDIT_ACCOUNT_OUTGOING_CONFIG) - putExtra(EXTRA_ACCOUNT_UUID, accountUuid) + data = NAVIGATION_ROUTE_ACCOUNT_EDIT_CONFIG_OUTGOING.withAccountUuid(accountUuid).toDeepLinkUri() } context.startActivity(intent) } diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt index a5762ed46f..5de11098ba 100644 --- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt +++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/navigation/FeatureLauncherNavHost.kt @@ -12,8 +12,6 @@ import app.k9mail.feature.launcher.FeatureLauncherExternalContract.AccountSetupF import app.k9mail.feature.launcher.FeatureLauncherExternalContract.ImportSettingsLauncher import app.k9mail.feature.onboarding.navigation.NAVIGATION_ROUTE_ONBOARDING import app.k9mail.feature.onboarding.navigation.onboardingRoute -import kotlinx.collections.immutable.ImmutableMap -import kotlinx.collections.immutable.persistentMapOf import org.koin.compose.koinInject @Composable @@ -21,7 +19,6 @@ fun FeatureLauncherNavHost( navController: NavHostController, onBack: () -> Unit, modifier: Modifier = Modifier, - startDestinationArguments: ImmutableMap = persistentMapOf(), importSettingsLauncher: ImportSettingsLauncher = koinInject(), accountSetupFinishedLauncher: AccountSetupFinishedLauncher = koinInject(), ) { @@ -41,7 +38,6 @@ fun FeatureLauncherNavHost( onFinish = { accountSetupFinishedLauncher.launch(it) }, ) accountEditRoute( - startDestinationArguments = startDestinationArguments, onBack = onBack, onFinish = { activity.finish() }, ) diff --git a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt index 6d24197aca..27aef780a5 100644 --- a/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt +++ b/feature/launcher/src/main/kotlin/app/k9mail/feature/launcher/ui/FeatureLauncherApp.kt @@ -9,13 +9,10 @@ import app.k9mail.core.ui.compose.common.activity.LocalActivity import app.k9mail.core.ui.compose.designsystem.atom.Background import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.feature.launcher.navigation.FeatureLauncherNavHost -import kotlinx.collections.immutable.ImmutableMap -import kotlinx.collections.immutable.persistentMapOf @Composable fun FeatureLauncherApp( modifier: Modifier = Modifier, - startDestinationArguments: ImmutableMap = persistentMapOf(), ) { val navController = rememberNavController() diff --git a/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt b/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt index f146364956..a9e2263afb 100644 --- a/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt +++ b/feature/onboarding/src/main/kotlin/app/k9mail/feature/onboarding/navigation/OnboardingNavigation.kt @@ -6,7 +6,7 @@ import androidx.navigation.NavOptions import app.k9mail.core.ui.compose.common.navigation.deepLinkComposable import app.k9mail.feature.onboarding.ui.OnboardingScreen -const val NAVIGATION_ROUTE_ONBOARDING = "/onboarding" +const val NAVIGATION_ROUTE_ONBOARDING = "onboarding" fun NavController.navigateToOnboarding( navOptions: NavOptions? = null, -- GitLab From 3d9235ce03c9c82e4718eeb8786073b8187f55a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolf-Martell=20Montw=C3=A9?= Date: Tue, 26 Sep 2023 16:59:43 +0200 Subject: [PATCH 88/94] Apply changes from renaming AccountLoader to AccountStateLoader --- .../feature/account/edit/AccountEditModule.kt | 2 +- .../edit/domain/usecase/LoadAccountState.kt | 18 +---- .../account/edit/AccountEditModuleKtTest.kt | 2 +- .../domain/usecase/LoadAccountStateTest.kt | 78 ++++++------------- 4 files changed, 29 insertions(+), 71 deletions(-) diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt index 1097d58bab..ca91aa4b0f 100644 --- a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/AccountEditModule.kt @@ -23,7 +23,7 @@ val featureAccountEditModule = module { factory { LoadAccountState( - accountLoader = get(), + accountStateLoader = get(), accountStateRepository = get(), ) } diff --git a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountState.kt b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountState.kt index ea0676ca28..832fe6d934 100644 --- a/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountState.kt +++ b/feature/account/edit/src/main/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountState.kt @@ -2,13 +2,11 @@ package app.k9mail.feature.account.edit.domain.usecase import app.k9mail.feature.account.common.AccountCommonExternalContract import app.k9mail.feature.account.common.domain.AccountDomainContract -import app.k9mail.feature.account.common.domain.entity.Account import app.k9mail.feature.account.common.domain.entity.AccountState -import app.k9mail.feature.account.common.domain.entity.AuthorizationState import app.k9mail.feature.account.edit.domain.AccountEditDomainContract class LoadAccountState( - private val accountLoader: AccountCommonExternalContract.AccountLoader, + private val accountStateLoader: AccountCommonExternalContract.AccountStateLoader, private val accountStateRepository: AccountDomainContract.AccountStateRepository, ) : AccountEditDomainContract.UseCase.LoadAccountState { override suspend fun execute(accountUuid: String): AccountState { @@ -21,21 +19,11 @@ class LoadAccountState( } private suspend fun loadState(accountUuid: String): AccountState { - val account = accountLoader.loadAccount(accountUuid) - return if (account != null) { - val accountState = account.mapToAccountState() + val accountState = accountStateLoader.loadAccountState(accountUuid) + return if (accountState != null) { accountState } else { AccountState(uuid = accountUuid) }.also { accountStateRepository.setState(it) } } - - private fun Account.mapToAccountState() = AccountState( - uuid = uuid, - emailAddress = emailAddress, - incomingServerSettings = incomingServerSettings, - outgoingServerSettings = outgoingServerSettings, - authorizationState = AuthorizationState(authorizationState), - options = options, - ) } diff --git a/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/AccountEditModuleKtTest.kt b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/AccountEditModuleKtTest.kt index 27ae9b1755..41954b7967 100644 --- a/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/AccountEditModuleKtTest.kt +++ b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/AccountEditModuleKtTest.kt @@ -31,7 +31,7 @@ import org.robolectric.RuntimeEnvironment class AccountEditModuleKtTest : KoinTest { private val externalModule: Module = module { - single { Mockito.mock() } + single { Mockito.mock() } single { Mockito.mock() } single { TrustedSocketFactory { _, _, _, _ -> null } diff --git a/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountStateTest.kt b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountStateTest.kt index b73953b5c9..9199820695 100644 --- a/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountStateTest.kt +++ b/feature/account/edit/src/test/kotlin/app/k9mail/feature/account/edit/domain/usecase/LoadAccountStateTest.kt @@ -1,7 +1,6 @@ package app.k9mail.feature.account.edit.domain.usecase import app.k9mail.feature.account.common.data.InMemoryAccountStateRepository -import app.k9mail.feature.account.common.domain.entity.Account import app.k9mail.feature.account.common.domain.entity.AccountOptions import app.k9mail.feature.account.common.domain.entity.AccountState import app.k9mail.feature.account.common.domain.entity.AuthorizationState @@ -10,6 +9,7 @@ import assertk.assertThat import assertk.assertions.isEqualTo import com.fsck.k9.mail.AuthType import com.fsck.k9.mail.ServerSettings +import kotlin.test.DefaultAsserter.fail import kotlinx.coroutines.test.runTest import org.junit.Test @@ -18,78 +18,39 @@ class LoadAccountStateTest { @Test fun `should load account state WHEN account in state repository has different UUID`() = runTest { val testSubject = LoadAccountState( - accountLoader = { accountUuid -> - Account( - uuid = accountUuid, - emailAddress = EMAIL_ADDRESS, - incomingServerSettings = INCOMING_SERVER_SETTINGS, - outgoingServerSettings = OUTGOING_SERVER_SETTINGS, - authorizationState = AUTHORIZATION_STATE, - options = OPTIONS, - ) + accountStateLoader = { _ -> + ACCOUNT_STATE }, - accountStateRepository = InMemoryAccountStateRepository(), + accountStateRepository = InMemoryAccountStateRepository( + state = ACCOUNT_STATE.copy(uuid = "differentUuid"), + ), ) val result = testSubject.execute(ACCOUNT_UUID) - assertThat(result).isEqualTo( - AccountState( - uuid = ACCOUNT_UUID, - emailAddress = EMAIL_ADDRESS, - incomingServerSettings = INCOMING_SERVER_SETTINGS, - outgoingServerSettings = OUTGOING_SERVER_SETTINGS, - authorizationState = AuthorizationState(AUTHORIZATION_STATE), - options = OPTIONS, - ), - ) + assertThat(result).isEqualTo(ACCOUNT_STATE) } @Test fun `should return account state WHEN account in state repository has same UUID`() = runTest { val testSubject = LoadAccountState( - accountLoader = { accountUuid -> - Account( - uuid = accountUuid, - emailAddress = EMAIL_ADDRESS, - incomingServerSettings = INCOMING_SERVER_SETTINGS, - outgoingServerSettings = OUTGOING_SERVER_SETTINGS, - authorizationState = AUTHORIZATION_STATE, - options = OPTIONS, - ) - }, - accountStateRepository = InMemoryAccountStateRepository().apply { - setState( - AccountState( - uuid = ACCOUNT_UUID, - emailAddress = EMAIL_ADDRESS, - incomingServerSettings = INCOMING_SERVER_SETTINGS, - outgoingServerSettings = OUTGOING_SERVER_SETTINGS, - authorizationState = AuthorizationState(AUTHORIZATION_STATE), - options = OPTIONS, - ), - ) + accountStateLoader = { _ -> + fail("AccountStateLoader should not be called in this test") }, + accountStateRepository = InMemoryAccountStateRepository( + state = ACCOUNT_STATE, + ), ) val result = testSubject.execute(ACCOUNT_UUID) - assertThat(result).isEqualTo( - AccountState( - uuid = ACCOUNT_UUID, - emailAddress = EMAIL_ADDRESS, - incomingServerSettings = INCOMING_SERVER_SETTINGS, - outgoingServerSettings = OUTGOING_SERVER_SETTINGS, - authorizationState = AuthorizationState(AUTHORIZATION_STATE), - options = OPTIONS, - ), - ) + assertThat(result).isEqualTo(ACCOUNT_STATE) } @Test fun `should return empty account state WHEN account loader returns null`() = runTest { val testSubject = LoadAccountState( - accountLoader = { null }, + accountStateLoader = { null }, accountStateRepository = InMemoryAccountStateRepository(), ) @@ -131,7 +92,7 @@ class LoadAccountStateTest { clientCertificateAlias = null, ) - const val AUTHORIZATION_STATE = "authorization state" + val AUTHORIZATION_STATE = AuthorizationState("authorization state") val OPTIONS = AccountOptions( accountName = "accountName", @@ -141,5 +102,14 @@ class LoadAccountStateTest { messageDisplayCount = 25, showNotification = true, ) + + val ACCOUNT_STATE = AccountState( + uuid = ACCOUNT_UUID, + emailAddress = EMAIL_ADDRESS, + incomingServerSettings = INCOMING_SERVER_SETTINGS, + outgoingServerSettings = OUTGOING_SERVER_SETTINGS, + authorizationState = AUTHORIZATION_STATE, + options = OPTIONS, + ) } } -- GitLab From eb9b560486617ba2233845112921b00a680ac264 Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 28 Sep 2023 16:30:44 +0200 Subject: [PATCH 89/94] Update translations --- .../legacy/src/main/res/values-ar/strings.xml | 3 +- .../legacy/src/main/res/values-be/strings.xml | 3 +- .../legacy/src/main/res/values-bg/strings.xml | 3 +- .../legacy/src/main/res/values-br/strings.xml | 3 +- .../legacy/src/main/res/values-ca/strings.xml | 5 +- .../legacy/src/main/res/values-cs/strings.xml | 3 +- .../legacy/src/main/res/values-cy/strings.xml | 3 +- .../legacy/src/main/res/values-da/strings.xml | 8 +- .../legacy/src/main/res/values-de/strings.xml | 5 +- .../legacy/src/main/res/values-el/strings.xml | 9 +- .../legacy/src/main/res/values-eo/strings.xml | 3 +- .../legacy/src/main/res/values-es/strings.xml | 5 +- .../legacy/src/main/res/values-et/strings.xml | 5 +- .../legacy/src/main/res/values-eu/strings.xml | 25 ++- .../legacy/src/main/res/values-fa/strings.xml | 12 +- .../legacy/src/main/res/values-fi/strings.xml | 5 +- .../legacy/src/main/res/values-fr/strings.xml | 5 +- .../legacy/src/main/res/values-fy/strings.xml | 5 +- .../legacy/src/main/res/values-gd/strings.xml | 3 +- .../legacy/src/main/res/values-gl/strings.xml | 3 +- .../legacy/src/main/res/values-hr/strings.xml | 1 + .../legacy/src/main/res/values-hu/strings.xml | 5 +- .../legacy/src/main/res/values-in/strings.xml | 3 +- .../legacy/src/main/res/values-is/strings.xml | 5 +- .../legacy/src/main/res/values-it/strings.xml | 5 +- .../legacy/src/main/res/values-iw/strings.xml | 3 +- .../legacy/src/main/res/values-ja/strings.xml | 9 +- .../legacy/src/main/res/values-ko/strings.xml | 1 + .../legacy/src/main/res/values-lt/strings.xml | 3 +- .../legacy/src/main/res/values-lv/strings.xml | 3 +- .../legacy/src/main/res/values-ml/strings.xml | 3 +- .../legacy/src/main/res/values-nb/strings.xml | 3 +- .../legacy/src/main/res/values-nl/strings.xml | 5 +- .../legacy/src/main/res/values-pl/strings.xml | 5 +- .../src/main/res/values-pt-rBR/strings.xml | 5 +- .../src/main/res/values-pt-rPT/strings.xml | 3 +- .../legacy/src/main/res/values-ro/strings.xml | 143 ++++++++++-------- .../legacy/src/main/res/values-ru/strings.xml | 3 +- .../legacy/src/main/res/values-sk/strings.xml | 3 +- .../legacy/src/main/res/values-sl/strings.xml | 3 +- .../legacy/src/main/res/values-sq/strings.xml | 5 +- .../legacy/src/main/res/values-sr/strings.xml | 3 +- .../legacy/src/main/res/values-sv/strings.xml | 7 +- .../legacy/src/main/res/values-tr/strings.xml | 3 +- .../legacy/src/main/res/values-uk/strings.xml | 7 +- .../src/main/res/values-zh-rCN/strings.xml | 5 +- .../src/main/res/values-zh-rTW/strings.xml | 3 +- 47 files changed, 244 insertions(+), 119 deletions(-) diff --git a/app/ui/legacy/src/main/res/values-ar/strings.xml b/app/ui/legacy/src/main/res/values-ar/strings.xml index c9bfb99d0f..e7a701e83a 100644 --- a/app/ui/legacy/src/main/res/values-ar/strings.xml +++ b/app/ui/legacy/src/main/res/values-ar/strings.xml @@ -28,7 +28,7 @@ اكتشف الجديد في هذا الإصدار عرض - + -- \nتم الإرسال من هاتفي الأندرويد بواسطة برنامج K-9. أعتذر عن الإيجاز. سيُحذف الحساب \"%s\" من الحسابات في K-9. @@ -1064,4 +1064,5 @@ الاسم وعنوان البريد الإلكتروني + diff --git a/app/ui/legacy/src/main/res/values-be/strings.xml b/app/ui/legacy/src/main/res/values-be/strings.xml index 1aeb5545aa..7d83048eda 100644 --- a/app/ui/legacy/src/main/res/values-be/strings.xml +++ b/app/ui/legacy/src/main/res/values-be/strings.xml @@ -28,7 +28,7 @@ Даведайцеся, што новага ў гэтым выпуску Праглядзець - + -- \nАдпраўлена з маёй прылады праз K-9 Mail. Выбачайце за сцісласць. Акаўнт \"%s\" будзе выдалены з K-9 Mail. @@ -1098,4 +1098,5 @@ Імя і адрас электроннай пошты + diff --git a/app/ui/legacy/src/main/res/values-bg/strings.xml b/app/ui/legacy/src/main/res/values-bg/strings.xml index b178cd08b6..b70e69ea92 100644 --- a/app/ui/legacy/src/main/res/values-bg/strings.xml +++ b/app/ui/legacy/src/main/res/values-bg/strings.xml @@ -24,7 +24,7 @@ Разбери какво ново в тази варсия - + -- \nИзпратено от моето Андроид у-во чрез K-9 Mail. Моля да ме извините за краткия ми изказ. Акаунтът \"%s\" ще бъде премахнат от K-9 Mail. @@ -990,4 +990,5 @@ Имейл адрес + diff --git a/app/ui/legacy/src/main/res/values-br/strings.xml b/app/ui/legacy/src/main/res/values-br/strings.xml index 8bf9211b61..9b2b0e66a8 100644 --- a/app/ui/legacy/src/main/res/values-br/strings.xml +++ b/app/ui/legacy/src/main/res/values-br/strings.xml @@ -13,7 +13,7 @@ Lañvaz - + -- \nKaset eus ma fellgomzer Android gant K-9 Mail. Dilamet e vo ar gont \"%s\" eus K-9 Mail. @@ -930,4 +930,5 @@ Gallout a rit mirout ar gemennadenn-mañ hag implij anezhi evel un enrolladenn e Chomlec’h postel + diff --git a/app/ui/legacy/src/main/res/values-ca/strings.xml b/app/ui/legacy/src/main/res/values-ca/strings.xml index 8fe917346c..45bb3d220a 100644 --- a/app/ui/legacy/src/main/res/values-ca/strings.xml +++ b/app/ui/legacy/src/main/res/values-ca/strings.xml @@ -28,7 +28,7 @@ Esbrineu les novetats d’aquesta versió. Vista - + -- \nEnviat des del meu dispositiu Android amb el K-9 Mail. Disculpeu la brevetat. El compte \"%s\" s\'eliminarà del K-9 Mail. @@ -1083,4 +1083,7 @@ Podeu desar aquest missatge i fer-lo servir com a còpia de seguretat per a la v Nom i adreça de correu + Se suprimeix el compte... + + sense llegir, %s diff --git a/app/ui/legacy/src/main/res/values-cs/strings.xml b/app/ui/legacy/src/main/res/values-cs/strings.xml index 07e9d33b5f..7682688152 100644 --- a/app/ui/legacy/src/main/res/values-cs/strings.xml +++ b/app/ui/legacy/src/main/res/values-cs/strings.xml @@ -28,7 +28,7 @@ Zjistěte, co je v tomto vydání nového Zobrazit - + -- \nOdesláno aplikací K-9 Mail ze systému Android. Omluvte prosím moji stručnost. Účet \"%s\" bude odstraněn z K-9 Mail. @@ -1096,4 +1096,5 @@ Tuto zprávu si můžete ponechat a použít jí jako zálohu svého tajného kl Jméno a adresa + diff --git a/app/ui/legacy/src/main/res/values-cy/strings.xml b/app/ui/legacy/src/main/res/values-cy/strings.xml index e232399e16..609803a532 100644 --- a/app/ui/legacy/src/main/res/values-cy/strings.xml +++ b/app/ui/legacy/src/main/res/values-cy/strings.xml @@ -27,7 +27,7 @@ Darganfod beth sy\'n newydd yn y diweddariad hwn - + -- \nAnfonwyd gyda K-9 Mail ar Android\n - yr ap ebost cyntaf yn y Gymraeg. Caiff y cyfrif \"%s\" ei dynnu o K-9 Mail. @@ -1068,4 +1068,5 @@ Mae\'n bosib i ti gadw\'r neges hon a\'i ddefnyddio wrth gefn fel dy allwedd gyf Cyfeiriad e-bost + diff --git a/app/ui/legacy/src/main/res/values-da/strings.xml b/app/ui/legacy/src/main/res/values-da/strings.xml index bbf10a7ffd..e1c31950d5 100644 --- a/app/ui/legacy/src/main/res/values-da/strings.xml +++ b/app/ui/legacy/src/main/res/values-da/strings.xml @@ -28,7 +28,7 @@ Find ud af hvad der er nyt i denne version Vis - + -- \nDette er sendt fra min mobiltelefon. Undskyld at jeg fatter mig i korthed. Kontoen \"%s\" vil blive fjernet fra K-9 Mail. @@ -254,6 +254,7 @@ Flyt + Tæthed Kompakt Standard Afslappet @@ -322,6 +323,7 @@ Slet på server Markér som læst på server Brug komprimering + Send klient ID Ryd slettede mails Umiddelbart efter sletning I forbindelse med hentning af mails @@ -406,6 +408,8 @@ Marker som læst ved sletning Marker en besked som læst når den bliver slettet Notifikation kategorier + Konfiguér notifikationer for nye beskeder + Konfiguér fejl og status notifikationer Vis altid billeder Aldrig Kun når afsender findes i Kontakter @@ -659,6 +663,7 @@ Animation Anvend visuelle effekter Vis Fælles Indbakke + Vis antal af stjernemarkeret Fælles indbakke Alle mails i fælles mapper Inkluder i fælles indbakke @@ -1064,4 +1069,5 @@ Beskeden kan beholdes og bruges som sikkerhedskopi til den hemmelige nøgle. Hvi Navn og email-adresse + diff --git a/app/ui/legacy/src/main/res/values-de/strings.xml b/app/ui/legacy/src/main/res/values-de/strings.xml index 30ddb82a80..b087256dcf 100644 --- a/app/ui/legacy/src/main/res/values-de/strings.xml +++ b/app/ui/legacy/src/main/res/values-de/strings.xml @@ -28,7 +28,7 @@ Finde heraus, was es Neues in diesem Release gibt Ansehen - + -- \nDiese Nachricht wurde von meinem Android-Gerät mit K-9 Mail gesendet. Das Konto \"%s\" wird aus K-9 Mail entfernt. @@ -1082,4 +1082,7 @@ Du kannst diese Nachricht aufheben und sie als Backup für deinen geheimen Schl Name und E-Mail-Adresse + Entfernen des Kontos… + + ungelesen, %s diff --git a/app/ui/legacy/src/main/res/values-el/strings.xml b/app/ui/legacy/src/main/res/values-el/strings.xml index 4a02f4a128..899003d1e2 100644 --- a/app/ui/legacy/src/main/res/values-el/strings.xml +++ b/app/ui/legacy/src/main/res/values-el/strings.xml @@ -28,7 +28,7 @@ Δείτε τι έχει αλλάξει σε αυτή την έκδοση Προβολή - + -- \nΣταλμένο από τη συσκευή μου Android με το K-9 Mail. Παρακαλώ συγχωρήστε την ολιγολογία μου. Ο λογαριασμός \'%s\' θα διαγραφεί από το K-9 Mail. @@ -196,6 +196,7 @@ + + εγώ Εμφάνιση αποκρυμμένων εικόνων Δεν υπάρχει πρόγραμμα προβολής για %s. @@ -256,7 +257,9 @@ Μετακίνηση Κενό μεταξύ στοιχείων + Συμπαγή Εξ ορισμού + Χαλαρό Απόκρυψη προγράμματος-πελάτη αλληλογραφίας Αφαίρεση του Πράκτορα-χρήστη K-9 από την επικεφαλίδα του μηνύματος Απόκρυψη ζώνης ώρας @@ -324,6 +327,7 @@ Να διαγράφεται άμεσα από τον εξυπηρετητή Επισήμανση ως αναγνωσμένο στον εξυπηρετητή Χρήση συμπίεσης + Αποστολή ID πελάτη Εξάλειψη διαγραμμένων μηνυμάτων Αμέσως Κατά την ενημέρωση @@ -1079,4 +1083,7 @@ \'Ονομα και διεύθυνση ηλ. ταχυδρομείου + Αφαίρεση λογαριασμού... + + αδιάβαστα, %s diff --git a/app/ui/legacy/src/main/res/values-eo/strings.xml b/app/ui/legacy/src/main/res/values-eo/strings.xml index 40ff007c9a..79bc27353b 100644 --- a/app/ui/legacy/src/main/res/values-eo/strings.xml +++ b/app/ui/legacy/src/main/res/values-eo/strings.xml @@ -25,7 +25,7 @@ Kio estas nova en tiu ĉi versio - + -- \nSendita per K-9 Retpoŝtilo. Bonvolu pardoni min por skribi mallonge. La konto \"%s\" estos forigita el K-9 Retpoŝtilo. @@ -1011,4 +1011,5 @@ Vi povas konservi tiun ĉi mesaĝon kaj uzi ĝin kiel sekurkopion de via privata Retpoŝta adreso + diff --git a/app/ui/legacy/src/main/res/values-es/strings.xml b/app/ui/legacy/src/main/res/values-es/strings.xml index 8d55dc98bd..44db4178cc 100644 --- a/app/ui/legacy/src/main/res/values-es/strings.xml +++ b/app/ui/legacy/src/main/res/values-es/strings.xml @@ -28,7 +28,7 @@ Descubre las novedades de esta versión Leer - + -- \nEnviado desde mi dispositivo Android con K-9 Mail. Por favor, disculpa mi brevedad. La cuenta \"%s\" será eliminada de K-9 Mail. @@ -1089,4 +1089,7 @@ Puedes guardar este mensaje y usarlo como copia de seguridad de tu clave secreta Nombre y dirección de correo + Borrando cuenta… + + sin leer, %s diff --git a/app/ui/legacy/src/main/res/values-et/strings.xml b/app/ui/legacy/src/main/res/values-et/strings.xml index f28e76432c..c182163b2f 100644 --- a/app/ui/legacy/src/main/res/values-et/strings.xml +++ b/app/ui/legacy/src/main/res/values-et/strings.xml @@ -28,7 +28,7 @@ Vaata mis on selles versioonis muutunud Vaata - + -- \nSaadetud Androidi seadmelt K-9 meiliga. Vabanda, et nii lühdalt. Konto \"%s\" eemaldatakse K-9 Mailist. @@ -1085,4 +1085,7 @@ Palun jäta see kiri alles ning kasuta seda muu hulgas oma krüptovõtme varunda Nimi ja e-posti aadress + Eemaldame kontot… + + lugemata, %s diff --git a/app/ui/legacy/src/main/res/values-eu/strings.xml b/app/ui/legacy/src/main/res/values-eu/strings.xml index 021d3049ad..962fdb5285 100644 --- a/app/ui/legacy/src/main/res/values-eu/strings.xml +++ b/app/ui/legacy/src/main/res/values-eu/strings.xml @@ -27,7 +27,8 @@ Ikusi zer den berria bertsio honetan - + Ikusi + -- \nAndroid gailutik bidalia K-9 Mail erabiliz. Barka laburtasuna. \"%s\" kontua K-9 Mail-etik kenduko da. @@ -190,9 +191,13 @@ Bcc: Ezin izan da eranskina gorde. + "honi: " + + + niri + Erakutsi urruneko irudiak Ezin da %s-(r)entzako ikustailerik aurkitu. Deskargatu mezu osoa %1$s-(r)en bidez @@ -250,7 +255,10 @@ Mugitu + Dentsitatea + Trinkoa Lehenetsia + Erlaxatua Ezkutatu posta bezeroa Kendu K-9 erabiltzaile-agentea posta goiburuetatik Ezkutatu ordu-zona @@ -318,6 +326,7 @@ Zerbitzarian ezabatu Zerbitzarian irakurritako gisa markatu Erabili konpresioa + Bidaltzaile bezero IDa Ezabatu hemen ere zerbitzaritik ezabatutako mezuak Berehala Atzitzean @@ -686,6 +695,7 @@ Kontu izena Bidaltzailea + Hartzaileak Gaia Ordua eta data Mezuaren gorputza @@ -938,7 +948,7 @@ Deszifratzea bertan behera utzi da. Saiatu berriro Zifratutako mezua deskargatu behar da deszifratzeko. - Errorea posta deszifratzean + Errorea e-posta deszifratzean Une honetan karaktere bereziak ez dira onartzen! Errorea helbidea analizatzean! Ezkutatu zifratu gabeko sinadurak @@ -1041,7 +1051,9 @@ Mezu hau gorde dezakezu eta zure gako sekretuaren babes-kopia gisa erabili. Hau Karpeta ez da aurkitu + Mezuaren xehetasunak + \'Data\' goiburua falta da Nork @@ -1055,12 +1067,21 @@ Mezu hau gorde dezakezu eta zure gako sekretuaren babes-kopia gisa erabili. Hau Bcc + Errorea gertatu da mezuaren xehetasunak kargatzean. + Gehitu kontaktuetara + Idatzi mezua honi: + Kopiatu e-posta helbidea + Kopiatu izena eta e-posta helbidea Posta helbidea + Izena eta e-posta helbidea + Kontua ezabatzen… + + irakurri gabea, %s diff --git a/app/ui/legacy/src/main/res/values-fa/strings.xml b/app/ui/legacy/src/main/res/values-fa/strings.xml index e2c152970f..d71a1bce43 100644 --- a/app/ui/legacy/src/main/res/values-fa/strings.xml +++ b/app/ui/legacy/src/main/res/values-fa/strings.xml @@ -9,7 +9,7 @@ The K-9 Dog Walkers کد منبع - مجوز آپاچی، نسخهٔ ۲٫۰ + مجوز آپاچی، نسخهٔ 2.0 پروژهٔ متن‌باز وبگاه راهنمای کاربر @@ -27,8 +27,8 @@ از تازه‌های این نسخه باخبر شوید - نما - + مشاهده + -- \nاز دستگاه اندرویدی‌ام و به‌وسیلهٔ K-9 Mail ارسال شد. حساب «%s» از K-9 Mail حذف خواهد شد. @@ -192,8 +192,9 @@ مخفیانه به: نمی‌توان پیوست را ذخیره کرد. - به + به  + + من @@ -1082,4 +1083,7 @@ نام و آدرس ایمیل + در حال حذف حساب… + + خوانده نشده، %s diff --git a/app/ui/legacy/src/main/res/values-fi/strings.xml b/app/ui/legacy/src/main/res/values-fi/strings.xml index e0457e6883..377d21c4bb 100644 --- a/app/ui/legacy/src/main/res/values-fi/strings.xml +++ b/app/ui/legacy/src/main/res/values-fi/strings.xml @@ -28,7 +28,7 @@ Selvitä mitä uutta tämä julkaisu sisältää Näytä - + -- \nLähetetty Android-laitteestani K-9 Maililla. Pahoittelut vähäsanaisuudestani. Tili \"%s\" poistetaan K-9 Mailista. @@ -1082,4 +1082,7 @@ Voit säilyttää tämän viestin ja käyttää sitä varmuuskopioina salausavai Nimi ja sähköpostiosoitteet + Poistetaan tili… + + lukematon, %s diff --git a/app/ui/legacy/src/main/res/values-fr/strings.xml b/app/ui/legacy/src/main/res/values-fr/strings.xml index 813bf879ff..607eacdade 100644 --- a/app/ui/legacy/src/main/res/values-fr/strings.xml +++ b/app/ui/legacy/src/main/res/values-fr/strings.xml @@ -28,7 +28,7 @@ Découvrez les nouveautés de cette version Afficher - + -- \nEnvoyé de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma brièveté. Le compte « %s » sera supprimé de Courriel K-9 Mail. @@ -1086,4 +1086,7 @@ Nom et adresse courriel + Suppression du compte… + + non lus, %s diff --git a/app/ui/legacy/src/main/res/values-fy/strings.xml b/app/ui/legacy/src/main/res/values-fy/strings.xml index c295f776b6..463da4ccf5 100644 --- a/app/ui/legacy/src/main/res/values-fy/strings.xml +++ b/app/ui/legacy/src/main/res/values-fy/strings.xml @@ -28,7 +28,7 @@ Untdek wat der nij is yn dizze ferzje Besjen - + -- \nFerstjoerd fan myn Android-apparaat ôf mei K-9 Mail. De account ‘%s’ wurdt út K-9 Mail fuortsmiten. @@ -1082,4 +1082,7 @@ Jo kinne dit berjocht bewarje as reservekopy foar jo geheime kaai. As jo dit dwa Namme en e-mailadres + Account fuortsmite… + + net lêzen, %s diff --git a/app/ui/legacy/src/main/res/values-gd/strings.xml b/app/ui/legacy/src/main/res/values-gd/strings.xml index 9bf039085c..b4e70affab 100644 --- a/app/ui/legacy/src/main/res/values-gd/strings.xml +++ b/app/ui/legacy/src/main/res/values-gd/strings.xml @@ -23,7 +23,7 @@ Na tha ùr - + -- Chaidh a chur le post /e/. Thèid an cunntas “%s” a thoirt air falbh on phost. @@ -920,4 +920,5 @@ Seòladh puist-d + diff --git a/app/ui/legacy/src/main/res/values-gl/strings.xml b/app/ui/legacy/src/main/res/values-gl/strings.xml index 1dabc2a174..8c1b229938 100644 --- a/app/ui/legacy/src/main/res/values-gl/strings.xml +++ b/app/ui/legacy/src/main/res/values-gl/strings.xml @@ -25,7 +25,7 @@ Mira as novidades deste lanzamento - + -- \nEnviado dende o meu teléfono Android con K-9 Mail. Desculpa a miña brevedade A conta \"%s\" será eliminada de K-9 Mail. @@ -1015,4 +1015,5 @@ Podes conservar esta mensaxe e usala como copia de seguridade da túa chave secr Enderezo electrónico + diff --git a/app/ui/legacy/src/main/res/values-hr/strings.xml b/app/ui/legacy/src/main/res/values-hr/strings.xml index 7eb496c9ba..91de9739ad 100644 --- a/app/ui/legacy/src/main/res/values-hr/strings.xml +++ b/app/ui/legacy/src/main/res/values-hr/strings.xml @@ -940,4 +940,5 @@ Adresa e-pošte + diff --git a/app/ui/legacy/src/main/res/values-hu/strings.xml b/app/ui/legacy/src/main/res/values-hu/strings.xml index e43608b297..ede0cd8fdb 100644 --- a/app/ui/legacy/src/main/res/values-hu/strings.xml +++ b/app/ui/legacy/src/main/res/values-hu/strings.xml @@ -28,7 +28,7 @@ Tudja meg, hogy mik az újdonságok ebben a kiadásban Megtekintés - + -- \nAndroidos készülékről küldve K-9 Mail használatával. Elnézést a rövidségért. A(z) „%s” fiók eltávolításra kerül a K-9 Mail alkalmazásból. @@ -1082,4 +1082,7 @@ Megtarthatja ezt az üzenetet, és felhasználhatja a titkos kulcs biztonsági m Név és e-mail cím + Fiók eltávolítása… + + olvasatlan, %s diff --git a/app/ui/legacy/src/main/res/values-in/strings.xml b/app/ui/legacy/src/main/res/values-in/strings.xml index 116acc70e7..4c08208a59 100644 --- a/app/ui/legacy/src/main/res/values-in/strings.xml +++ b/app/ui/legacy/src/main/res/values-in/strings.xml @@ -25,7 +25,7 @@ Apa yang baru - + -- \nDikirim dari perangkat Android saya menggunakan K-9 Mail. Akun \"%s\" akan dibuang dari K-9 Mail. @@ -973,4 +973,5 @@ Anda dapat menyimpan pesan ini dan menggunakannya sebagai cadangan untuk kunci r Alamat surel + diff --git a/app/ui/legacy/src/main/res/values-is/strings.xml b/app/ui/legacy/src/main/res/values-is/strings.xml index ea764e065d..2d3063415e 100644 --- a/app/ui/legacy/src/main/res/values-is/strings.xml +++ b/app/ui/legacy/src/main/res/values-is/strings.xml @@ -28,7 +28,7 @@ Skoðaðu hvað sé nýtt við þessa útgáfu Skoða - + -- \nSent úr Android tækinu mínu með K-9 póstforritinu. Afsakaðu hvað ég stytti mál mitt mikið. Aðgangurinn \"%s\" verður fjarlægður úr K-9 póstinum. @@ -1083,4 +1083,7 @@ Til að setja Autocrypt upp á nýju tæki, farðu þá eftir leiðbeiningunum s Nafn og tölvupóstfang + Fjarlægi aðgang… + + ólesið, %s diff --git a/app/ui/legacy/src/main/res/values-it/strings.xml b/app/ui/legacy/src/main/res/values-it/strings.xml index 5c7a6ecaa2..a3624be257 100644 --- a/app/ui/legacy/src/main/res/values-it/strings.xml +++ b/app/ui/legacy/src/main/res/values-it/strings.xml @@ -28,7 +28,7 @@ Scopri le novità di questa versione Vedi - + -- \nInviato dal mio dispositivo Android con K-9 Mail. Perdonate la brevità. L\'account \"%s\" sarà rimosso da K-9 Mail. @@ -1090,4 +1090,7 @@ Puoi conservare questo messaggio e utilizza come una copia di sicurezza della tu Nome e indirizzo email + Rimozione account… + + nuovi messaggi, %s diff --git a/app/ui/legacy/src/main/res/values-iw/strings.xml b/app/ui/legacy/src/main/res/values-iw/strings.xml index c925655ec3..2e34b60a82 100644 --- a/app/ui/legacy/src/main/res/values-iw/strings.xml +++ b/app/ui/legacy/src/main/res/values-iw/strings.xml @@ -20,7 +20,7 @@ גלה מה חדש בגירסא זו - + -- \nנשלח ממכשיר האנדרואיד שלי בעזרת אפליקציית הדואר K-9. סלח לי על הקצרנות. החשבון \"%s\" יימחק מדואר K-9 . @@ -641,4 +641,5 @@ כתובת דוא\"ל + diff --git a/app/ui/legacy/src/main/res/values-ja/strings.xml b/app/ui/legacy/src/main/res/values-ja/strings.xml index b672816abc..75650b7c90 100644 --- a/app/ui/legacy/src/main/res/values-ja/strings.xml +++ b/app/ui/legacy/src/main/res/values-ja/strings.xml @@ -13,7 +13,7 @@ オープンソースプロジェクト ウェブサイト ユーザーマニュアル - 助けを得る + ヘルプ ユーザーフォーラム Fediverse Twitter @@ -25,10 +25,10 @@ 新着 アプリの更新後に更新内容を表示 - このリリースは何が新しいのかを知る + このリリースの更新内容を確認する 表示 - + -- \nK-9 Mail で Android デバイスから送信しました。簡単で申し訳ありません。 アカウント \"%s\" はK-9 Mailから削除されます。 @@ -1075,4 +1075,7 @@ 名前とメールアドレス + アカウントを削除しています… + + 未読、%s diff --git a/app/ui/legacy/src/main/res/values-ko/strings.xml b/app/ui/legacy/src/main/res/values-ko/strings.xml index 7e1317b059..c5163b27f0 100644 --- a/app/ui/legacy/src/main/res/values-ko/strings.xml +++ b/app/ui/legacy/src/main/res/values-ko/strings.xml @@ -841,4 +841,5 @@ 전자우편 주소 + diff --git a/app/ui/legacy/src/main/res/values-lt/strings.xml b/app/ui/legacy/src/main/res/values-lt/strings.xml index 66f2fe1963..74ebb6e6d1 100644 --- a/app/ui/legacy/src/main/res/values-lt/strings.xml +++ b/app/ui/legacy/src/main/res/values-lt/strings.xml @@ -27,7 +27,7 @@ Sužinokite, kas naujo šioje versijoje - + - \nIšsiųsta iš mano Android įrenginio naudojant K-9 Mail. Atleiskite už trumpumą. Paskyra \"%s\" bus pašalinta iš „K-9 Mail“. @@ -1082,4 +1082,5 @@ Norėdami nustatyti automatinį šifravimą naujajame prietaise, vadovaukitės i Vardas ir el. pašto adresas + diff --git a/app/ui/legacy/src/main/res/values-lv/strings.xml b/app/ui/legacy/src/main/res/values-lv/strings.xml index acec7983a5..ac51d72bf4 100644 --- a/app/ui/legacy/src/main/res/values-lv/strings.xml +++ b/app/ui/legacy/src/main/res/values-lv/strings.xml @@ -28,7 +28,7 @@ Uzzināt, kas jauns šajā versijā Skatīt - + -- \nNosūtīts ar K-9 Pastu no manas Android ierīces. Atvainojiet, ka esmu tik kodolīgs. Konts \"%s\" tiks noņemts no K-9 Pasta. @@ -1090,4 +1090,5 @@ Lai jaunajā ierīcē iestatītu automātisko šifrēšanu, lūdzu sekojiet nor Vārds un e-pasta adrese + diff --git a/app/ui/legacy/src/main/res/values-ml/strings.xml b/app/ui/legacy/src/main/res/values-ml/strings.xml index 9d9a2398cc..51d4022856 100644 --- a/app/ui/legacy/src/main/res/values-ml/strings.xml +++ b/app/ui/legacy/src/main/res/values-ml/strings.xml @@ -25,7 +25,7 @@ ഈ റിലീസിൽ പുതിയത് എന്താണെന്ന് കണ്ടെത്തുക - + -- \nകെ-9 മെയിൽ ഉപയോഗിച്ച് എന്റെ ആൻഡ്രോയിഡിൽ നിന്നും അയച്ചത്. ദയവായി എന്റെ പദപ്രയോഗമിതത്വം ക്ഷമിക്കുക. കെ-9 മെയിലിൽ നിന്ന് \"%s\" അക്കൗണ്ട് നീക്കംചെയ്യും. @@ -1002,4 +1002,5 @@ ഇമെയിൽ വിലാസം + diff --git a/app/ui/legacy/src/main/res/values-nb/strings.xml b/app/ui/legacy/src/main/res/values-nb/strings.xml index 0210019d67..aac226befc 100644 --- a/app/ui/legacy/src/main/res/values-nb/strings.xml +++ b/app/ui/legacy/src/main/res/values-nb/strings.xml @@ -20,7 +20,7 @@ Hva er nytt? - + -- \nSendt fra min Android-enhet med K-9 e-post. Unnskyld min kortfattethet. Kontoen \"%s\" vil bli fjernet fra K-9 e-post @@ -943,4 +943,5 @@ til %d flere E-postadresse + diff --git a/app/ui/legacy/src/main/res/values-nl/strings.xml b/app/ui/legacy/src/main/res/values-nl/strings.xml index 5afc5fce04..ea9c88cf84 100644 --- a/app/ui/legacy/src/main/res/values-nl/strings.xml +++ b/app/ui/legacy/src/main/res/values-nl/strings.xml @@ -28,7 +28,7 @@ Ontdek wat er nieuw is in deze versie Bekijken - + -- \nVerstuurd vanaf mijn Android-apparaat met K-9 Mail. De account ‘%s’ wordt uit K-9 Mail verwijderd. @@ -1082,4 +1082,7 @@ Je kunt dit bericht bewaren als back-up voor de geheime sleutel. Als je dit wilt Naam en e-mailadres + Account verwijderen… + + ongelezen, %s diff --git a/app/ui/legacy/src/main/res/values-pl/strings.xml b/app/ui/legacy/src/main/res/values-pl/strings.xml index b7a9fcc655..76b86a01f2 100644 --- a/app/ui/legacy/src/main/res/values-pl/strings.xml +++ b/app/ui/legacy/src/main/res/values-pl/strings.xml @@ -28,7 +28,7 @@ Dowiedz się, co nowego w tej wersji Wyświetl - + -- Wysłane z urządzenia Android za pomocą K-9 Mail. Proszę wybaczyć moją zwięzłość. @@ -1097,4 +1097,7 @@ Tą wiadomość można zachować i użyć w formie kopii zapasowej twojego klucz Nazwa oraz adres e-mail + Usuwanie konta… + + nieprzeczytane, %s diff --git a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml index c1ebb3f3bd..4a1a5acdc8 100644 --- a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml +++ b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml @@ -28,7 +28,7 @@ Descubra as novidades dessa versão Ver - + -- \nEnviado de meu dispositivo Android com K-9 mail. Desculpe-me pela brevidade. A conta \"%s\" será removida do K-9 Mail. @@ -1089,4 +1089,7 @@ Você pode guardar esta mensagem e usá-la como um backup da sua chave secreta. Nome e endereço de e-mail + Removendo a conta... + + não lidas, 1 %s diff --git a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml index 90aa9ae511..814bcaca2d 100644 --- a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml +++ b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml @@ -28,7 +28,7 @@ Descubra o que há de novo nesta versão Ver - + -- \nEnviado a partir do meu dispositivo Android com o K-9 Mail. Peço desculpa pela brevidade. A conta \"%s\" será removida do K-9 Mail. @@ -1090,4 +1090,5 @@ Pode manter esta mensagem e usá-la como uma cópia de segurança para a sua cha Nome e endereço de email + diff --git a/app/ui/legacy/src/main/res/values-ro/strings.xml b/app/ui/legacy/src/main/res/values-ro/strings.xml index 6abddbd7df..ac47210e56 100644 --- a/app/ui/legacy/src/main/res/values-ro/strings.xml +++ b/app/ui/legacy/src/main/res/values-ro/strings.xml @@ -13,7 +13,7 @@ Proiect Open Source Website Manualul utilizatorului - Obțineți ajutor + Obține ajutor Forum utilizatori Fediverse Twitter @@ -23,12 +23,13 @@ Nu s-a putut încărca jurnalul de modificări. Versiune %s Ce este nou - Afișați modificările recente atunci când aplicația a fost actualizată + Afișează modificările recente atunci când aplicația a fost actualizată - Aflați ce este nou în această versiune + Află ce este nou în această versiune - - -- \nTrimis de pe dispozitivul meu Android cu K-9 Mail. Rog scuzați mesajul scurt. + Vizualizare + + -- \nTrimis de pe dispozitivul meu Android cu K-9 Mail. Rog scuzați concizia mea. Contul \"%s\" va fi șters din K-9 Mail. @@ -43,8 +44,8 @@ Trimite atașat Alege contul Alege dosar - Mutați la… - Copiați la… + Mută la… + Copiază la… %d selectate Înainte @@ -73,18 +74,18 @@ Adaugă cont Compune Caută - Căutați peste tot + Caută peste tot Rezultate căutare Mesaje noi Opțiuni Gestionează dosarele Opțiuni cont - Ștergeți contul + Șterge contul Marchează ca citit Distribuie Alege expeditor Adaugă steluță - Șterge steluță + Șterge steluța Copiază Dezabonare Arată antete @@ -140,7 +141,7 @@ cel mult încă %d Eroare de notificare - S-a produs o eroare în timpul încercării de a crea o notificare de sistem pentru un mesaj nou. Motivul este cel mai probabil lipsa unui sunet de notificare.\n\nApăsați pentru a deschide setările de notificare. + S-a produs o eroare în timpul încercării de a crea o notificare de sistem pentru un mesaj nou. Motivul este cel mai probabil lipsa unui sunet de notificare.\n\nApasă pentru a deschide setările de notificare. Se verifică emailul: %1$s:%2$s Se verifică emailul Se trimite emailul: %s @@ -164,7 +165,7 @@ cel mult încă %d Jurnalizează informații sensibile Poate include parole în jurnale. Jurnalele de export - Exportul a avut succes. Jurnalele pot conține informații sensibile. Aveți grijă cui le trimiteți. + Exportul a avut succes. Jurnalele pot conține informații sensibile. Ai grijă cui le trimiți. Exportul a eșuat. Încarcă mai multe mesaje Către:%s @@ -179,7 +180,7 @@ cel mult încă %d Cc: %s a scris: În %1$s, %2$s a scris: - Trebuie să adăugi cel puțin un destinatar. + Trebuie să adaugi cel puțin un destinatar. Câmpul Destinatar conține date incomplete! Nu a putut fi găsită adresa de e-mail pentru acest contact. Unele atașamente nu pot fi redirecționate pentru că nu au fost descărcate. @@ -199,10 +200,10 @@ cel mult încă %d eu - Afișați imagini la distanță + Afișează imagini de la distanță Nu se poate găsi vizualizator pentru %s. Descarcă mesajul complet - via %1$s + prin %1$s Mai multe de la acest expeditor Mesaj aruncat Mesaj salvat ca ciornă @@ -235,7 +236,7 @@ cel mult încă %d Marchează toate mesajele ca citite Șterge (din notificare) - Acțiuni de glisare + Acțiuni la glisare Glisarea spre dreapta @@ -249,7 +250,7 @@ cel mult încă %d Adăugare/eliminare stea - Arhivă + Arhivare Şterge @@ -257,7 +258,10 @@ cel mult încă %d Mută + Densitate + Compact Implicit + Relaxat Ascunde clientul de mail Elimină K-9 User-Agent din anteturile mesajelor Ascunde fusul orar @@ -281,23 +285,23 @@ cel mult încă %d Configurarează un cont nou Adresa e-mail Parolă - Pentru a utiliza acest cont de e-mail cu K-9 Mail, trebuie să vă conectați și să acordați aplicației acces la e-mailurile dumneavoastră. + Pentru a utiliza acest cont de e-mail cu K-9 Mail, trebuie să te conectezi și să acorzi aplicației acces la e-mailuri. - Conectați-vă + Conectează-te - Conectați-vă cu Google + Conectează-te cu Google - Pentru a vă vedea parola aici, activați blocarea ecranului pe acest dispozitiv. + Pentru a vedea parola aici, activează blocarea ecranului pe acest dispozitiv. Verifică-ți identitatea - Deblocare pentru a vedea parola dumneavoastră + Deblochează pentru a-ți vedea parola Setare manuală - Preluarea informațiilor de cont\u2026 + Preluarea informațiilor contului\u2026 Verificarea setărilor serverului de intrare\u2026 Verificarea setărilor serverului de expediere\u2026 - Autentifică\u2026 + Autentificare\u2026 Preluarea setărilor contului\u2026 - Se întrerupe\u2026 + Se anulează\u2026 Tipul contului Ce fel de cont este acesta? POP3 @@ -321,13 +325,14 @@ cel mult încă %d STARTTLS \"%1$s = %2$s\" nu este valabilă cu \"%3$s = %4$s\" Când şterg un mesaj - Nu şterge de pe server + Nu se șterge de pe server Şterge de pe server Marchează ca citit pe server - Utilizați compresia + Utilizează comprimarea + Trimite ID-ul clientului Elimină mesajele şterse de pe server Imediat - Când interoghează + La interogare Manual Auto-detectare IMAP namespace Prefix cale IMAP @@ -367,7 +372,7 @@ cel mult încă %d La fiecare 36 de minute La fiecare 48 de minute La fiecare 60 de minute - Număr de mesaje afișate + Numărul de mesaje afișate 10 mesaje 25 mesaje 50 mesaje @@ -409,15 +414,15 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Arată o notificare pentru mesajele pe care le-am trimis Doar contacte Arată notificări doar pentru mesaje de la persoane cunoscute - Ignorați mesajele de chat - Ignorați mesajele de chat + Ignoră mesajele de chat + Nu afișa notificări pentru mesajele aparținând unui chat prin e-mail Marchează ca citit la deschidere - Marchează mesaj ca citit când e deschis pentru vizualizare + Marchează mesajul ca citit când e deschis pentru vizualizare Marchează ca citit la ștergere Marchează un mesaj ca citit când este șters Categorii de notificări - Configurați notificările pentru mesaje noi - Configurați notificările de eroare și de stare + Configurează notificările pentru mesaje noi + Configurează notificările de eroare și de stare Arată întotdeauna imaginile Nu De la contacte @@ -460,7 +465,7 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Culoarea contului Culoarea contului folosită în lista de dosare și conturi Mărimea dosarului local - Aduce mesaje până la + Preia mesaje până la 1 KiB 2 KiB 4 KiB @@ -530,7 +535,7 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Niciunul Nivel 1 Nivel 2 - Same as poll class + La fel ca clasa de sondaj Nivel notificare dosar Niciunul Nivel 1 @@ -570,9 +575,9 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Opțiuni compunere mesaj Setări implicite compunere mesaj Setează ”De la”, Bcc și semnătură - Administrează identități + Administrează identitățile Setează adrese și semnături alternative pentru ”De la” - Gestionează identități + Gestionează identitățile Gestionează identitate Modifică identitate Salvează @@ -658,7 +663,7 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Sincronizare în fundal Niciodată Întotdeauna - Când \'Auto-sync\' este activat + Când \'Sincronizarea automată\' este bifată Selectează tot Maxim de dosare de verificat prin push 5 dosare @@ -672,8 +677,8 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Animații Folosește efecte vizuale gaudi Navigarea prin butoanele de volum in afișarea tip mesaj - Afișați Cutia poștală de intrare unificată - Afișați numărul de stele + Afișează Cutia poștală de intrare unificată + Afișează numărul de stele Căsuță poștală unificată Toate mesajele în dosare unificate Unifică @@ -712,11 +717,11 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Nu s-a găsit o aplicație potrivită pentru această acțiune. Trimitere eșuată: %s Salvezi ca ciornă? - Salvezi sau Renunți la mesaj? - Salvați sau respingeți modificările? + Salvezi sau renunți la mesaj? + Salvezi sau renunți la modificări? Renunți la mesaj? Sigur dorești să renunți la mesaj? - Eliminare mesaje locale? + Elimini mesajele locale? Această acțiune va elimina toate mesejele locale din dosar. Niciun mesaj nu va fi șters de pe server. Elimină mesajele Confirmă ștergerea @@ -743,7 +748,7 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Da Nu Se descarcă anexa - Backup + Copie de rezervă Diverse Exportă setările Exportă @@ -758,9 +763,9 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Te rog introduce parolele - Vă rugăm să vă înregistrați + Conectează-te - Vă rugăm să vă conectați și să introduceți parolele + Conectează-te și introdu parolele Importarea setărilor a eșuat Citirea fișierului cu setări a eșuat Importarea unor setări a eșuat @@ -867,9 +872,9 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Folosește certificat client Fără certificat client Elimină selecția certificatului client - Eșuare recuperare certificat client pentru aliasul \"%s\" + Eșuare recuperare certificat client pentru alias-ul \"%s\" Opțiuni avansate - Certificatul client \"%1$s\" a expirat sau nu este încă valid (%2$s) + Certificatul clientului \"%1$s\" a expirat sau nu este încă valid (%2$s) *Criptat* Adaugă din Contacte @@ -877,7 +882,7 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Bcc Către De la - Răspundeți la + Răspunde la <Unknown Recipient> <Unknown Sender> Acasă @@ -943,8 +948,8 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru dar criptarea nu e considerată sigură OK Caută Cheie - Vezi Semnatar - Vezi Expeditor + Vezi Semnatarul + Vezi Expeditorul Detalii Deblochează Această parte nu a fost criptată și poate fi nesigură. @@ -962,7 +967,7 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Criptare indisponibilă în modul „Doar semnare”! Text nesemnat Acest mesaj este criptat - Acest mesaj a fost criptat cu OpenPGP.\nPentru a-l citi trebuie să instalați și să configurați o aplicație OpenPGP compatibilă. + Acest mesaj a fost criptat cu OpenPGP.\nPentru a-l citi trebuie să instalezi și să configurezi o aplicație OpenPGP compatibilă. Mergi la Setări Listă mesaje K-9 @@ -1022,20 +1027,20 @@ Poți păstra acest mesaj și să îl folosești drept copie de siguranță a ch Așteptând noi e-mailuri Adormire până când este permisă sincronizarea în fundal În așteptare până când rețeaua este disponibilă - Apăsați pentru a afla mai multe. + Apasă pentru a afla mai multe. Informații despre Push Atunci când se utilizează Push, K-9 Mail menține o conexiune cu serverul de e-mail. Android necesită afișarea unei notificări în curs de desfășurare în timp ce aplicația este activă în fundal. %s - Cu toate acestea, Android vă permite, de asemenea, să ascundeți notificarea. - Aflați mai multe - Configurați notificarea - Dacă nu aveți nevoie de notificări instantanee cu privire la mesajele noi, dezactivați funcția Push și utilizați funcția Polling. Polling verifică dacă există mesaje noi la intervale regulate și nu are nevoie de notificare. - Dezactivați Push + Cu toate acestea, Android permite, de asemenea, ascunderea notificării. + Află mai multe + Configurează notificarea + Dacă nu ai nevoie de notificări instantanee cu privire la mesajele noi, dezactivează funcția Push și utilizează funcția Sondaj. Sondaj verifică dacă există mesaje noi la intervale regulate și nu are nevoie de notificare. + Dezactivare Push Selectează Deselectează - Marcați citit + Marchează ca citit Marchează ca necitit @@ -1049,13 +1054,13 @@ Poți păstra acest mesaj și să îl folosești drept copie de siguranță a ch Spam - Mutați… + Mutare… - Afișați butonul flotant de compunere + Afișează butonul flotant de compunere Eroare - Nu s-a găsit folderul + Nu s-a găsit dosarul Detalii despre mesaj @@ -1065,7 +1070,7 @@ Poți păstra acest mesaj și să îl folosești drept copie de siguranță a ch Expeditor - Răspundeți la + Răspunde la Către @@ -1075,15 +1080,19 @@ Poți păstra acest mesaj și să îl folosești drept copie de siguranță a ch S-a produs o eroare la încărcarea detaliilor mesajului. - Adăugați la contacte + Adaugă din contacte + Compune mesaj pentru - Copiați adresa de e-mail + Copiază adresa de e-mail - Copiați numele și adresa de e-mail + Copiază numele și adresa de e-mail Adresa e-mail Numele și adresa de e-mail + Se elimină contul… + + necitit, %s diff --git a/app/ui/legacy/src/main/res/values-ru/strings.xml b/app/ui/legacy/src/main/res/values-ru/strings.xml index debdc15a83..9e800262d8 100644 --- a/app/ui/legacy/src/main/res/values-ru/strings.xml +++ b/app/ui/legacy/src/main/res/values-ru/strings.xml @@ -28,7 +28,7 @@ Узнайте, что нового в этом выпуске Показать - + -- \nПростите за краткость, создано в K-9 Mail. Учётная запись «%s» будет удалена из приложения K-9 Mail. @@ -1096,4 +1096,5 @@ Имя и адрес эл. почты + diff --git a/app/ui/legacy/src/main/res/values-sk/strings.xml b/app/ui/legacy/src/main/res/values-sk/strings.xml index b86f8dd65c..3cc945ad7d 100644 --- a/app/ui/legacy/src/main/res/values-sk/strings.xml +++ b/app/ui/legacy/src/main/res/values-sk/strings.xml @@ -22,7 +22,7 @@ Verzia %s - + -- \nOdoslané z môjho Android zariadenia prostredníctvom K-9 Mail. Prosím, ospravedlňte moju stručnosť. Účet \"%s\" bude odstránený z K-9 Mail. @@ -887,4 +887,5 @@ E-mailová adresa + diff --git a/app/ui/legacy/src/main/res/values-sl/strings.xml b/app/ui/legacy/src/main/res/values-sl/strings.xml index 3a2a05e0de..67d8fa51c2 100644 --- a/app/ui/legacy/src/main/res/values-sl/strings.xml +++ b/app/ui/legacy/src/main/res/values-sl/strings.xml @@ -27,7 +27,7 @@ Kaj je novega v tej izdaji - + -- \nPoslano s programom K-9 Mail. Račun »%s« bo odstranjen iz programa. @@ -1091,4 +1091,5 @@ Sporočilo lahko shranite in ga uporabite kot varno kopijo šifrirnega ključa. Ime in e-poštni naslov + diff --git a/app/ui/legacy/src/main/res/values-sq/strings.xml b/app/ui/legacy/src/main/res/values-sq/strings.xml index 38a052ce1c..60392caac8 100644 --- a/app/ui/legacy/src/main/res/values-sq/strings.xml +++ b/app/ui/legacy/src/main/res/values-sq/strings.xml @@ -28,7 +28,7 @@ Mësoni ç\’ka të re në këtë hedhje në qarkullim Shiheni - + -- \nDërguar nga pajisja ime Android, me K-9 Mail. Ju lutem, më ndjeni për shkurtësinë. Llogaria \“%s\” do të hiqet që nga K-9 Mail. @@ -1082,4 +1082,7 @@ Mund ta mbani këtë mesazh dhe ta përdorni si një kopjeruatje të kyçit tuaj Emër dhe adresë email + Po hiqet llogaria… + + të palexuar, %s diff --git a/app/ui/legacy/src/main/res/values-sr/strings.xml b/app/ui/legacy/src/main/res/values-sr/strings.xml index eae894f488..5a71f6d5fb 100644 --- a/app/ui/legacy/src/main/res/values-sr/strings.xml +++ b/app/ui/legacy/src/main/res/values-sr/strings.xml @@ -22,7 +22,7 @@ Верзија %s - + -- \nПослато К-9 Поштом са мог Андроид уређаја. Извините због сажетости. Налог „%s“ ће бити уклоњен из К-9 Поште. @@ -983,4 +983,5 @@ Адреса е-поште + diff --git a/app/ui/legacy/src/main/res/values-sv/strings.xml b/app/ui/legacy/src/main/res/values-sv/strings.xml index 1ce3aaec98..1b93be8938 100644 --- a/app/ui/legacy/src/main/res/values-sv/strings.xml +++ b/app/ui/legacy/src/main/res/values-sv/strings.xml @@ -28,7 +28,7 @@ Ta reda på vad som är nytt i denna utgåva Visa - + -- \nSkickat från min Android-enhet med K-9 Mail. Ursäkta min korthet. Kontot \"%s\" kommer att tas bort från K-9 Mail. @@ -63,7 +63,7 @@ Redigera som nytt meddelande Flytta Flytta till utkast - Arkivera om… + Återarkivera… Klar Kassera Spara som utkast @@ -1083,4 +1083,7 @@ Du kan behålla detta meddelande och använda det som en säkerhetskopia för di Namn och e-postadress + Tar bort konto... + + oläst, %s diff --git a/app/ui/legacy/src/main/res/values-tr/strings.xml b/app/ui/legacy/src/main/res/values-tr/strings.xml index 537b09060d..428ae16c62 100644 --- a/app/ui/legacy/src/main/res/values-tr/strings.xml +++ b/app/ui/legacy/src/main/res/values-tr/strings.xml @@ -27,7 +27,7 @@ Bu sürümdeki yenilikleri öğrenin - + -- \nAndroid için K-9 Posta\'dan gönderildi. Lütfen bu kısa notumu mazur görün. Hesap \"%s\" K-9 Mail\'den kaldırılacak. @@ -1047,4 +1047,5 @@ Bu iletiyi saklayabilir ve gizli anahtarınız için bir yedekleme olarak kullan E-posta adresi + diff --git a/app/ui/legacy/src/main/res/values-uk/strings.xml b/app/ui/legacy/src/main/res/values-uk/strings.xml index b9059c4b28..c262f2ce21 100644 --- a/app/ui/legacy/src/main/res/values-uk/strings.xml +++ b/app/ui/legacy/src/main/res/values-uk/strings.xml @@ -28,7 +28,7 @@ Дізнатися, що нового у цьому релізі Показати - + -- \nВідправлено з мого Android-пристрою за допомогою додатка K-9 Mail. Вибачте за стислість. Обліковий запис \"%s\" буде вилучено з K-9 Mail. @@ -200,7 +200,7 @@ + - мене + мені Показати зображення Не знайдено додаток для перегляду %s. @@ -1097,4 +1097,7 @@ Ім\'я та адреса ел. пошти + Видалення облікового запису... + + Непрочитані, %s diff --git a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml index 432862fd2e..8974ab327b 100644 --- a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml +++ b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml @@ -28,7 +28,7 @@ 了解此版本的新增功能 查看 - + -- \n使用 K-9 Mail 发送自我的Android设备。 即将从 K-9 Mail 中移除账户“%s”。 @@ -1075,4 +1075,7 @@ 姓名和电子邮箱地址 + 删除账户中… + + 未读,%s diff --git a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml index d864c41e37..c5ce6ccb63 100644 --- a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml +++ b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml @@ -28,7 +28,7 @@ 了解此版本的新增功能 檢視 - + -- \n使用 K-9 Mail 寄送。來自我的 Android 裝置。 帳號「%s」將從 K-9 Mail 中刪除。 @@ -1075,4 +1075,5 @@ 姓名和電子郵件地址 + -- GitLab From c297913bb7e0d8e72eab89a10b54e7ec0d9ebbf6 Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 28 Sep 2023 16:33:48 +0200 Subject: [PATCH 90/94] Replace occurrences of "..." with Unicode ellipsis character --- app/ui/legacy/src/main/res/values-ar/strings.xml | 6 +++--- app/ui/legacy/src/main/res/values-be/strings.xml | 2 +- app/ui/legacy/src/main/res/values-bg/strings.xml | 6 +++--- app/ui/legacy/src/main/res/values-ca/strings.xml | 2 +- app/ui/legacy/src/main/res/values-cy/strings.xml | 2 +- app/ui/legacy/src/main/res/values-da/strings.xml | 6 +++--- app/ui/legacy/src/main/res/values-el/strings.xml | 4 ++-- app/ui/legacy/src/main/res/values-eu/strings.xml | 2 +- app/ui/legacy/src/main/res/values-gl/strings.xml | 4 ++-- app/ui/legacy/src/main/res/values-it/strings.xml | 2 +- app/ui/legacy/src/main/res/values-iw/strings.xml | 4 ++-- app/ui/legacy/src/main/res/values-lt/strings.xml | 10 +++++----- app/ui/legacy/src/main/res/values-ml/strings.xml | 4 ++-- app/ui/legacy/src/main/res/values-pt-rBR/strings.xml | 2 +- app/ui/legacy/src/main/res/values-ru/strings.xml | 2 +- app/ui/legacy/src/main/res/values-sv/strings.xml | 2 +- app/ui/legacy/src/main/res/values-tr/strings.xml | 6 +++--- app/ui/legacy/src/main/res/values-uk/strings.xml | 4 ++-- 18 files changed, 35 insertions(+), 35 deletions(-) diff --git a/app/ui/legacy/src/main/res/values-ar/strings.xml b/app/ui/legacy/src/main/res/values-ar/strings.xml index e7a701e83a..271afed63e 100644 --- a/app/ui/legacy/src/main/res/values-ar/strings.xml +++ b/app/ui/legacy/src/main/res/values-ar/strings.xml @@ -306,7 +306,7 @@ التحقق من إعدادات الخادم الوارد \ u2026 التحقق من إعدادات خادم الصادر… المصادقة \u2026 - إحضار إعدادات الحساب ... + إحضار إعدادات الحساب … جارٍ الإلغاء\u2026 نوع الحساب ما نوع هذا الحساب؟ @@ -774,7 +774,7 @@ كلمة مرور خادم البريد الصادر استخدم نفس كلمة المرور لخادم البريد الصادر اسم الخادم: %s - إظهار العدد غير المقروء لـ ... + إظهار العدد غير المقروء لـ … الحساب الحساب الذي يجب عرض العدد غير المقروء له البريد الوارد الموحَّد @@ -982,7 +982,7 @@ تقوم رسالة إعداد Autocrypt بمشاركة الإعداد الشامل الخاص بك بأمان مع الأجهزة الأخرى. إرسال رسالة الإعداد سيتم إرسال الرسالة إلى عنوانك: - جاري إنشاء رسالة الإعداد ... + جاري إنشاء رسالة الإعداد … إرسال رسالة إلى: للإنهاء ، افتح الرسالة على جهازك الآخر وأدخل رمز الإعداد. إظهار كود الإعداد diff --git a/app/ui/legacy/src/main/res/values-be/strings.xml b/app/ui/legacy/src/main/res/values-be/strings.xml index 7d83048eda..d74919ce8d 100644 --- a/app/ui/legacy/src/main/res/values-be/strings.xml +++ b/app/ui/legacy/src/main/res/values-be/strings.xml @@ -959,7 +959,7 @@ Разблакаваць Гэтая частка незашыфраваная, таму небяспечная. Неабароненыя ўкладзеныя файлы - Загрузка... + Загрузка… Расшыфроўка скасаваная. Паўтарыць Для расшыфроўкі зашыфраваны ліст патрэбна спампаваць. diff --git a/app/ui/legacy/src/main/res/values-bg/strings.xml b/app/ui/legacy/src/main/res/values-bg/strings.xml index b70e69ea92..cf82d612a4 100644 --- a/app/ui/legacy/src/main/res/values-bg/strings.xml +++ b/app/ui/legacy/src/main/res/values-bg/strings.xml @@ -409,7 +409,7 @@ Настройване на ключа за криптиране от край-докрай Няма избрано OpenPGP приложение Свързан с %s - Конфигуриране ... + Конфигуриране … Съхранявайте всички чернови в криптиран вид Всички чернови ще се съхраняват криптирани Криптира чернови само ако е криптирането е активирано @@ -917,7 +917,7 @@ Autocrypt съобщение с настройки сигурно споделя от край-до-край вашите настройките с други устройства. Изпрати съобщение с настройки Съобщението ще бъде изпратено до следния адрес: - Създаване на съобщение с настройки... + Създаване на съобщение с настройки… Изпращане на съобщение до: За да завършите, отворете съобщението на друго устройство и въведете кодът за достъп. Показване на код за достъп @@ -935,7 +935,7 @@ Позволи достъп до контакти За да може да предоставя предложения за контакти и да показва имена на контакти и снимки, приложението се нуждае от достъп до вашите контакти. Възникна грешка при зареждането на данните - Инициализира... + Инициализира… Изчаква за нови съобщения Заспива докато синхронизирането на заден фон е разрешено Спи докато чака за мрежа diff --git a/app/ui/legacy/src/main/res/values-ca/strings.xml b/app/ui/legacy/src/main/res/values-ca/strings.xml index 45bb3d220a..a9e89929de 100644 --- a/app/ui/legacy/src/main/res/values-ca/strings.xml +++ b/app/ui/legacy/src/main/res/values-ca/strings.xml @@ -1083,7 +1083,7 @@ Podeu desar aquest missatge i fer-lo servir com a còpia de seguretat per a la v Nom i adreça de correu - Se suprimeix el compte... + Se suprimeix el compte… sense llegir, %s diff --git a/app/ui/legacy/src/main/res/values-cy/strings.xml b/app/ui/legacy/src/main/res/values-cy/strings.xml index 609803a532..581782cc3c 100644 --- a/app/ui/legacy/src/main/res/values-cy/strings.xml +++ b/app/ui/legacy/src/main/res/values-cy/strings.xml @@ -43,7 +43,7 @@ Anfon ymlaen fel atodiad Dewis cyfrif Dewis ffolder - Symud i... + Symud i… Copïo i… %d wedi\'i dewis Nesaf diff --git a/app/ui/legacy/src/main/res/values-da/strings.xml b/app/ui/legacy/src/main/res/values-da/strings.xml index e1c31950d5..6a46121944 100644 --- a/app/ui/legacy/src/main/res/values-da/strings.xml +++ b/app/ui/legacy/src/main/res/values-da/strings.xml @@ -44,8 +44,8 @@ Videresend som vedhæftet Vælg konto Vælg mappe - Flyt til... - Kopier til... + Flyt til… + Kopier til… %d valgt Næste @@ -1034,7 +1034,7 @@ Beskeden kan beholdes og bruges som sikkerhedskopi til den hemmelige nøgle. Hvi Spam - Flyt... + Flyt… Fejl diff --git a/app/ui/legacy/src/main/res/values-el/strings.xml b/app/ui/legacy/src/main/res/values-el/strings.xml index 899003d1e2..1c7e23dfa1 100644 --- a/app/ui/legacy/src/main/res/values-el/strings.xml +++ b/app/ui/legacy/src/main/res/values-el/strings.xml @@ -1045,7 +1045,7 @@ Ανεπιθύμητα - Μετακίνηση... + Μετακίνηση… Εμφάνιση εικονιδίου σύνθεσης @@ -1083,7 +1083,7 @@ \'Ονομα και διεύθυνση ηλ. ταχυδρομείου - Αφαίρεση λογαριασμού... + Αφαίρεση λογαριασμού… αδιάβαστα, %s diff --git a/app/ui/legacy/src/main/res/values-eu/strings.xml b/app/ui/legacy/src/main/res/values-eu/strings.xml index 962fdb5285..368db44dfa 100644 --- a/app/ui/legacy/src/main/res/values-eu/strings.xml +++ b/app/ui/legacy/src/main/res/values-eu/strings.xml @@ -1043,7 +1043,7 @@ Mezu hau gorde dezakezu eta zure gako sekretuaren babes-kopia gisa erabili. Hau Zabor-posta - Mugitu... + Mugitu… Erakutsi idazteko botoi flotagarria diff --git a/app/ui/legacy/src/main/res/values-gl/strings.xml b/app/ui/legacy/src/main/res/values-gl/strings.xml index 8c1b229938..b99a3ab706 100644 --- a/app/ui/legacy/src/main/res/values-gl/strings.xml +++ b/app/ui/legacy/src/main/res/values-gl/strings.xml @@ -941,7 +941,7 @@ Unha mensaxe de configuración de Autocrypt comparte de forma segura a túa configuración de extremo a extremo con outros dispositivos. Enviar mensaxe de configuración Esta mensaxe enviarase ao seguinte enderezo: - Xerando unha configuración da mensaxe... + Xerando unha configuración da mensaxe… Enviando a mensaxe a: Para rematar, abra a mensaxe noutro dispositivo e insira a ocnfiguración do código. Amosar a configuración do código @@ -959,7 +959,7 @@ Podes conservar esta mensaxe e usala como copia de seguridade da túa chave secr Permitir acceso aos contactos Para poder proporcionar suxestións de contactos e amosar os nomes e as fotos dos contactos, o aplicativo precisa acceder aos teus contactos. Ocorreu un erro mentres se estaban cargando os datos - Iniciando... + Iniciando… Agardando por novos correos Suspender ata que sexa permitida a sincronización de fondo Suspender ata que estea dispoñible a rede diff --git a/app/ui/legacy/src/main/res/values-it/strings.xml b/app/ui/legacy/src/main/res/values-it/strings.xml index a3624be257..9a3f42bb76 100644 --- a/app/ui/legacy/src/main/res/values-it/strings.xml +++ b/app/ui/legacy/src/main/res/values-it/strings.xml @@ -1052,7 +1052,7 @@ Puoi conservare questo messaggio e utilizza come una copia di sicurezza della tu Spam - Sposta... + Sposta… Mostra pulsante flottante Componi diff --git a/app/ui/legacy/src/main/res/values-iw/strings.xml b/app/ui/legacy/src/main/res/values-iw/strings.xml index 2e34b60a82..ad02ed0c96 100644 --- a/app/ui/legacy/src/main/res/values-iw/strings.xml +++ b/app/ui/legacy/src/main/res/values-iw/strings.xml @@ -35,8 +35,8 @@ העבר כקובץ מצורף בחר חשבון בחר תיקייה - העבר אל... - העתק אל... + העבר אל… + העתק אל… %d נבחרו הבא diff --git a/app/ui/legacy/src/main/res/values-lt/strings.xml b/app/ui/legacy/src/main/res/values-lt/strings.xml index 74ebb6e6d1..6e87c36760 100644 --- a/app/ui/legacy/src/main/res/values-lt/strings.xml +++ b/app/ui/legacy/src/main/res/values-lt/strings.xml @@ -43,8 +43,8 @@ Persiųsti kaip priedą Pasirinkti Paskyrą Pasirinkti aplanką - Perkelti į... - Kopijuoti į... + Perkelti į… + Kopijuoti į… %d pasirinkta Kitas @@ -447,7 +447,7 @@ Konfiguruoti visapusišką raktą Nesukonfigūruota OpenPGP programa Prisijungta prie %s - Konfiguruojama... + Konfiguruojama… Laikyti visus juodraščius užšifruotus Visi juodraščiai bus saugomi užšifruoti Šifruoti juodraščius tik tada, jei įjungtas šifravimas @@ -999,7 +999,7 @@ Automatinio šifravimo sąrankos laiške saugiai bendrinama visapuse sąranka su kitais prietaisais. Siųsti sąrankos laišką Šis laiškas bus išsiųstas jūsų adresu: - Generuojamas sąrankos laiškas... + Generuojamas sąrankos laiškas… Siunčiamas laiškas į: Kad baigti, atidarykite laišką kitame prietaise ir įveskite sąrankos kodą. Rodyti sąrankos kodą @@ -1017,7 +1017,7 @@ Norėdami nustatyti automatinį šifravimą naujajame prietaise, vadovaukitės i Leisti prieigą prie kontaktų Kad galėtų teikti kontaktų pasiūlymus ir rodyti kontaktų vardus bei nuotraukas, programėlei reikia prieigos prie jūsų kontaktų. Įkeliant duomenis įvyko klaida - Inicializuojama... + Inicializuojama… Laukiama naujų laiškų Miegama iki kol fono sinchronizacija bus leidžiama Miegama, kol bus prieinamas tinklas diff --git a/app/ui/legacy/src/main/res/values-ml/strings.xml b/app/ui/legacy/src/main/res/values-ml/strings.xml index 51d4022856..4ea210a9e6 100644 --- a/app/ui/legacy/src/main/res/values-ml/strings.xml +++ b/app/ui/legacy/src/main/res/values-ml/strings.xml @@ -41,8 +41,8 @@ അറ്റാച്ചുമെന്റായി ഫോർവേഡ് ചെയ്യുക അക്കൗണ്ട് തിരഞ്ഞെടുക്കുക ഫോൾഡർ തിരഞ്ഞെടുക്കുക - ഇതിലേക്ക് നീക്കുക... - ഇതിലേക്ക് പകർത്തുക... + ഇതിലേക്ക് നീക്കുക… + ഇതിലേക്ക് പകർത്തുക… %d തിരഞ്ഞെടുത്തു അടുത്തത് diff --git a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml index 4a1a5acdc8..c3ef2eb492 100644 --- a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml +++ b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml @@ -1089,7 +1089,7 @@ Você pode guardar esta mensagem e usá-la como um backup da sua chave secreta. Nome e endereço de e-mail - Removendo a conta... + Removendo a conta… não lidas, 1 %s diff --git a/app/ui/legacy/src/main/res/values-ru/strings.xml b/app/ui/legacy/src/main/res/values-ru/strings.xml index 9e800262d8..cae0fcee43 100644 --- a/app/ui/legacy/src/main/res/values-ru/strings.xml +++ b/app/ui/legacy/src/main/res/values-ru/strings.xml @@ -1058,7 +1058,7 @@ Отправить в спам - Переместить в... + Переместить в… Показать плавающую кнопку создания сообщения diff --git a/app/ui/legacy/src/main/res/values-sv/strings.xml b/app/ui/legacy/src/main/res/values-sv/strings.xml index 1b93be8938..2c814062b7 100644 --- a/app/ui/legacy/src/main/res/values-sv/strings.xml +++ b/app/ui/legacy/src/main/res/values-sv/strings.xml @@ -1083,7 +1083,7 @@ Du kan behålla detta meddelande och använda det som en säkerhetskopia för di Namn och e-postadress - Tar bort konto... + Tar bort konto… oläst, %s diff --git a/app/ui/legacy/src/main/res/values-tr/strings.xml b/app/ui/legacy/src/main/res/values-tr/strings.xml index 428ae16c62..554d4f7054 100644 --- a/app/ui/legacy/src/main/res/values-tr/strings.xml +++ b/app/ui/legacy/src/main/res/values-tr/strings.xml @@ -43,8 +43,8 @@ Ek olarak ilet Hesap Seçin Klasör Seç - Şuraya taşı... - Şuraya kopyala... + Şuraya taşı… + Şuraya kopyala… %d seçildi Sonraki @@ -1018,7 +1018,7 @@ Bu iletiyi saklayabilir ve gizli anahtarınız için bir yedekleme olarak kullan Gereksiz posta - Taşı... + Taşı… Hata diff --git a/app/ui/legacy/src/main/res/values-uk/strings.xml b/app/ui/legacy/src/main/res/values-uk/strings.xml index c262f2ce21..56bef84ce8 100644 --- a/app/ui/legacy/src/main/res/values-uk/strings.xml +++ b/app/ui/legacy/src/main/res/values-uk/strings.xml @@ -1059,7 +1059,7 @@ Спам - Перемістити... + Перемістити… Показати плаваючу кнопку створення повідомлення @@ -1097,7 +1097,7 @@ Ім\'я та адреса ел. пошти - Видалення облікового запису... + Видалення облікового запису… Непрочитані, %s -- GitLab From da0134cf2d58513acdf7e2ab2fd6963c80fb8a70 Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 28 Sep 2023 17:30:13 +0200 Subject: [PATCH 91/94] Change `message_view_recipient_prefix` to not require a trailing space Use a format string instead of a string that needs to end in a space for most languages. A trailing space is something that is easy to miss in most translation UIs. --- .../ui/messageview/RecipientLayoutCreator.kt | 30 ++++++------------- .../k9/ui/messageview/RecipientNamesView.kt | 2 +- .../legacy/src/main/res/values-ar/strings.xml | 4 +-- .../legacy/src/main/res/values-be/strings.xml | 4 +-- .../legacy/src/main/res/values-bg/strings.xml | 2 +- .../legacy/src/main/res/values-br/strings.xml | 2 +- .../legacy/src/main/res/values-ca/strings.xml | 4 +-- .../legacy/src/main/res/values-cs/strings.xml | 4 +-- .../legacy/src/main/res/values-cy/strings.xml | 2 +- .../legacy/src/main/res/values-da/strings.xml | 4 +-- .../legacy/src/main/res/values-de/strings.xml | 4 +-- .../legacy/src/main/res/values-el/strings.xml | 4 +-- .../src/main/res/values-en-rGB/strings.xml | 2 +- .../legacy/src/main/res/values-eo/strings.xml | 2 +- .../legacy/src/main/res/values-es/strings.xml | 4 +-- .../legacy/src/main/res/values-et/strings.xml | 4 +-- .../legacy/src/main/res/values-eu/strings.xml | 4 +-- .../legacy/src/main/res/values-fa/strings.xml | 4 +-- .../legacy/src/main/res/values-fi/strings.xml | 4 +-- .../legacy/src/main/res/values-fr/strings.xml | 4 +-- .../legacy/src/main/res/values-fy/strings.xml | 4 +-- .../legacy/src/main/res/values-gd/strings.xml | 2 +- .../legacy/src/main/res/values-gl/strings.xml | 2 +- .../legacy/src/main/res/values-hr/strings.xml | 2 +- .../legacy/src/main/res/values-hu/strings.xml | 4 +-- .../legacy/src/main/res/values-in/strings.xml | 2 +- .../legacy/src/main/res/values-is/strings.xml | 4 +-- .../legacy/src/main/res/values-it/strings.xml | 4 +-- .../legacy/src/main/res/values-iw/strings.xml | 2 +- .../legacy/src/main/res/values-ja/strings.xml | 2 +- .../legacy/src/main/res/values-ko/strings.xml | 2 +- .../legacy/src/main/res/values-lt/strings.xml | 4 +-- .../legacy/src/main/res/values-lv/strings.xml | 4 +-- .../legacy/src/main/res/values-ml/strings.xml | 2 +- .../legacy/src/main/res/values-nb/strings.xml | 2 +- .../legacy/src/main/res/values-nl/strings.xml | 4 +-- .../legacy/src/main/res/values-pl/strings.xml | 4 +-- .../src/main/res/values-pt-rBR/strings.xml | 4 +-- .../src/main/res/values-pt-rPT/strings.xml | 4 +-- .../legacy/src/main/res/values-ro/strings.xml | 4 +-- .../legacy/src/main/res/values-ru/strings.xml | 4 +-- .../legacy/src/main/res/values-sk/strings.xml | 2 +- .../legacy/src/main/res/values-sl/strings.xml | 4 +-- .../legacy/src/main/res/values-sq/strings.xml | 4 +-- .../legacy/src/main/res/values-sr/strings.xml | 2 +- .../legacy/src/main/res/values-sv/strings.xml | 4 +-- .../legacy/src/main/res/values-tr/strings.xml | 2 +- .../legacy/src/main/res/values-uk/strings.xml | 4 +-- .../src/main/res/values-zh-rCN/strings.xml | 4 +-- .../src/main/res/values-zh-rTW/strings.xml | 4 +-- app/ui/legacy/src/main/res/values/strings.xml | 4 +-- .../messageview/RecipientLayoutCreatorTest.kt | 2 +- 52 files changed, 92 insertions(+), 104 deletions(-) diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/RecipientLayoutCreator.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/RecipientLayoutCreator.kt index f8f2c4ddf5..bd500573e5 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/RecipientLayoutCreator.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/RecipientLayoutCreator.kt @@ -1,7 +1,5 @@ package com.fsck.k9.ui.messageview -import android.text.SpannableStringBuilder - private const val LIST_SEPARATOR = ", " /** @@ -19,7 +17,7 @@ private const val LIST_SEPARATOR = ", " internal class RecipientLayoutCreator( private val textMeasure: TextMeasure, private val maxNumberOfRecipientNames: Int, - private val recipientsPrefix: String, + private val recipientsFormat: String, private val additionalRecipientSpacing: Int, private val additionalRecipientsPrefix: String, ) { @@ -30,14 +28,9 @@ internal class RecipientLayoutCreator( ): RecipientLayoutData { require(recipientNames.isNotEmpty()) - val displayRecipientsBuilder = SpannableStringBuilder() - if (recipientNames.size == 1) { - displayRecipientsBuilder.append(recipientsPrefix) - displayRecipientsBuilder.append(recipientNames.first()) - return RecipientLayoutData( - recipientNames = displayRecipientsBuilder, + recipientNames = recipientsFormat.format(recipientNames.first()), additionalRecipients = null, ) } @@ -46,12 +39,11 @@ internal class RecipientLayoutCreator( val maxRecipientNames = recipientNames.size.coerceAtMost(maxNumberOfRecipientNames) for (numberOfDisplayRecipients in maxRecipientNames downTo 2) { - displayRecipientsBuilder.clear() - displayRecipientsBuilder.append(recipientsPrefix) - - recipientNames.asSequence() + val recipientNamesString = recipientNames.asSequence() .take(numberOfDisplayRecipients) - .joinTo(displayRecipientsBuilder, separator = LIST_SEPARATOR) + .joinToString(separator = LIST_SEPARATOR) + + val displayRecipients = recipientsFormat.format(recipientNamesString) additionalRecipientsBuilder.setLength(0) val numberOfAdditionalRecipients = totalNumberOfRecipients - numberOfDisplayRecipients @@ -60,20 +52,16 @@ internal class RecipientLayoutCreator( additionalRecipientsBuilder.append(numberOfAdditionalRecipients) } - if (doesTextFitAvailableWidth(displayRecipientsBuilder, additionalRecipientsBuilder, availableWidth)) { + if (doesTextFitAvailableWidth(displayRecipients, additionalRecipientsBuilder, availableWidth)) { return RecipientLayoutData( - recipientNames = displayRecipientsBuilder, + recipientNames = displayRecipients, additionalRecipients = additionalRecipientsBuilder.toStringOrNull(), ) } } - displayRecipientsBuilder.clear() - displayRecipientsBuilder.append(recipientsPrefix) - displayRecipientsBuilder.append(recipientNames.first()) - return RecipientLayoutData( - recipientNames = displayRecipientsBuilder, + recipientNames = recipientsFormat.format(recipientNames.first()), additionalRecipients = "$additionalRecipientsPrefix${totalNumberOfRecipients - 1}", ) } diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/RecipientNamesView.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/RecipientNamesView.kt index 5c82354de2..3753b03221 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/RecipientNamesView.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/RecipientNamesView.kt @@ -68,7 +68,7 @@ class RecipientNamesView(context: Context, attrs: AttributeSet?) : ViewGroup(con recipientLayoutCreator = RecipientLayoutCreator( textMeasure = textMeasure, maxNumberOfRecipientNames = MAX_NUMBER_OF_RECIPIENT_NAMES, - recipientsPrefix = context.getString(R.string.message_view_recipient_prefix), + recipientsFormat = context.getString(R.string.message_view_recipients_format), additionalRecipientSpacing = additionRecipientSpacing, additionalRecipientsPrefix = context.getString(R.string.message_view_additional_recipient_prefix), ) diff --git a/app/ui/legacy/src/main/res/values-ar/strings.xml b/app/ui/legacy/src/main/res/values-ar/strings.xml index 271afed63e..093602b105 100644 --- a/app/ui/legacy/src/main/res/values-ar/strings.xml +++ b/app/ui/legacy/src/main/res/values-ar/strings.xml @@ -199,8 +199,8 @@ نسخة كربونية : نسخة مخفية: غير قادر على حفظ المُرفَق. - - إلي + + إلي %s + diff --git a/app/ui/legacy/src/main/res/values-be/strings.xml b/app/ui/legacy/src/main/res/values-be/strings.xml index d74919ce8d..70ee6338db 100644 --- a/app/ui/legacy/src/main/res/values-be/strings.xml +++ b/app/ui/legacy/src/main/res/values-be/strings.xml @@ -195,8 +195,8 @@ Копія: Схаваная копія: Немагчыма захаваць далучаныя файлы. - - "да " + + да %s + diff --git a/app/ui/legacy/src/main/res/values-bg/strings.xml b/app/ui/legacy/src/main/res/values-bg/strings.xml index cf82d612a4..637a4389a9 100644 --- a/app/ui/legacy/src/main/res/values-bg/strings.xml +++ b/app/ui/legacy/src/main/res/values-bg/strings.xml @@ -180,7 +180,7 @@ Копие: Bcc: Не може да запази прикачения файл. - + diff --git a/app/ui/legacy/src/main/res/values-br/strings.xml b/app/ui/legacy/src/main/res/values-br/strings.xml index 9b2b0e66a8..490485ef4f 100644 --- a/app/ui/legacy/src/main/res/values-br/strings.xml +++ b/app/ui/legacy/src/main/res/values-br/strings.xml @@ -161,7 +161,7 @@ Cc: Bcc: N\'haller ket enrollañ ar stagadenn. - + diff --git a/app/ui/legacy/src/main/res/values-ca/strings.xml b/app/ui/legacy/src/main/res/values-ca/strings.xml index a9e89929de..4cdd9f2a05 100644 --- a/app/ui/legacy/src/main/res/values-ca/strings.xml +++ b/app/ui/legacy/src/main/res/values-ca/strings.xml @@ -191,8 +191,8 @@ A/c: Bcc: No s\'ha pogut desar l\'adjunt. - - "a " + + a %s + diff --git a/app/ui/legacy/src/main/res/values-cs/strings.xml b/app/ui/legacy/src/main/res/values-cs/strings.xml index 7682688152..094bfa09b2 100644 --- a/app/ui/legacy/src/main/res/values-cs/strings.xml +++ b/app/ui/legacy/src/main/res/values-cs/strings.xml @@ -195,8 +195,8 @@ Kopie: Skrytá kopie (Bcc): Přílohu se nedaří uložit. - - "komu " + + komu %s + diff --git a/app/ui/legacy/src/main/res/values-cy/strings.xml b/app/ui/legacy/src/main/res/values-cy/strings.xml index 581782cc3c..8e6f2de8f7 100644 --- a/app/ui/legacy/src/main/res/values-cy/strings.xml +++ b/app/ui/legacy/src/main/res/values-cy/strings.xml @@ -194,7 +194,7 @@ Cc: Bcc: Methu â chadw\'r atodiad. - + diff --git a/app/ui/legacy/src/main/res/values-da/strings.xml b/app/ui/legacy/src/main/res/values-da/strings.xml index 6a46121944..a459659149 100644 --- a/app/ui/legacy/src/main/res/values-da/strings.xml +++ b/app/ui/legacy/src/main/res/values-da/strings.xml @@ -189,8 +189,8 @@ Cc: Bcc: Kunne ikke gemme vedhæftning. - - "til " + + til %s + diff --git a/app/ui/legacy/src/main/res/values-de/strings.xml b/app/ui/legacy/src/main/res/values-de/strings.xml index b087256dcf..d9a42fdec6 100644 --- a/app/ui/legacy/src/main/res/values-de/strings.xml +++ b/app/ui/legacy/src/main/res/values-de/strings.xml @@ -190,8 +190,8 @@ CC: BCC: Anhang konnte nicht gespeichert werden. - - "an " + + an %s + diff --git a/app/ui/legacy/src/main/res/values-el/strings.xml b/app/ui/legacy/src/main/res/values-el/strings.xml index 1c7e23dfa1..e8f7904ea2 100644 --- a/app/ui/legacy/src/main/res/values-el/strings.xml +++ b/app/ui/legacy/src/main/res/values-el/strings.xml @@ -191,8 +191,8 @@ Κοιν: Κρυφή κοιν: Αδυναμία αποθήκευσης συνημμένου. - - σε + + σε %s + diff --git a/app/ui/legacy/src/main/res/values-en-rGB/strings.xml b/app/ui/legacy/src/main/res/values-en-rGB/strings.xml index e392f87d14..e16d41c602 100644 --- a/app/ui/legacy/src/main/res/values-en-rGB/strings.xml +++ b/app/ui/legacy/src/main/res/values-en-rGB/strings.xml @@ -16,7 +16,7 @@ - + diff --git a/app/ui/legacy/src/main/res/values-eo/strings.xml b/app/ui/legacy/src/main/res/values-eo/strings.xml index 79bc27353b..7a7f66fd06 100644 --- a/app/ui/legacy/src/main/res/values-eo/strings.xml +++ b/app/ui/legacy/src/main/res/values-eo/strings.xml @@ -179,7 +179,7 @@ Kopio: Kaŝkopio: Ne povis konservi kunsendaĵon. - + diff --git a/app/ui/legacy/src/main/res/values-es/strings.xml b/app/ui/legacy/src/main/res/values-es/strings.xml index 44db4178cc..6248565f4c 100644 --- a/app/ui/legacy/src/main/res/values-es/strings.xml +++ b/app/ui/legacy/src/main/res/values-es/strings.xml @@ -192,8 +192,8 @@ Cc: Cco: No se puede guardar el adjunto. - - "para " + + para %s + diff --git a/app/ui/legacy/src/main/res/values-et/strings.xml b/app/ui/legacy/src/main/res/values-et/strings.xml index c182163b2f..36bd310a32 100644 --- a/app/ui/legacy/src/main/res/values-et/strings.xml +++ b/app/ui/legacy/src/main/res/values-et/strings.xml @@ -191,8 +191,8 @@ Koopia: Pimekoopia: Manuse salvestamine ebaõnnestus - - "saajaks " + + saajaks %s + diff --git a/app/ui/legacy/src/main/res/values-eu/strings.xml b/app/ui/legacy/src/main/res/values-eu/strings.xml index 368db44dfa..c06cb03298 100644 --- a/app/ui/legacy/src/main/res/values-eu/strings.xml +++ b/app/ui/legacy/src/main/res/values-eu/strings.xml @@ -190,8 +190,8 @@ Cc: Bcc: Ezin izan da eranskina gorde. - - "honi: " + + honi: %s + diff --git a/app/ui/legacy/src/main/res/values-fa/strings.xml b/app/ui/legacy/src/main/res/values-fa/strings.xml index d71a1bce43..4d175bce57 100644 --- a/app/ui/legacy/src/main/res/values-fa/strings.xml +++ b/app/ui/legacy/src/main/res/values-fa/strings.xml @@ -191,8 +191,8 @@ رونوشت به: مخفیانه به: نمی‌توان پیوست را ذخیره کرد. - - به  + + به %s + diff --git a/app/ui/legacy/src/main/res/values-fi/strings.xml b/app/ui/legacy/src/main/res/values-fi/strings.xml index 377d21c4bb..f33387294e 100644 --- a/app/ui/legacy/src/main/res/values-fi/strings.xml +++ b/app/ui/legacy/src/main/res/values-fi/strings.xml @@ -190,8 +190,8 @@ Kopio: Piilokopio: Liitteen tallentaminen epäonnistui. - - "vastaanottaja " + + vastaanottaja %s + diff --git a/app/ui/legacy/src/main/res/values-fr/strings.xml b/app/ui/legacy/src/main/res/values-fr/strings.xml index 607eacdade..3d49033a71 100644 --- a/app/ui/legacy/src/main/res/values-fr/strings.xml +++ b/app/ui/legacy/src/main/res/values-fr/strings.xml @@ -194,8 +194,8 @@ Cc : Cci : Impossible d’enregistrer le fichier joint. - - "à " + + à %s + diff --git a/app/ui/legacy/src/main/res/values-fy/strings.xml b/app/ui/legacy/src/main/res/values-fy/strings.xml index 463da4ccf5..49a3931927 100644 --- a/app/ui/legacy/src/main/res/values-fy/strings.xml +++ b/app/ui/legacy/src/main/res/values-fy/strings.xml @@ -190,8 +190,8 @@ Cc: Bcc: Kin bylage net bewarje. - - "oan " + + oan %s + diff --git a/app/ui/legacy/src/main/res/values-gd/strings.xml b/app/ui/legacy/src/main/res/values-gd/strings.xml index b4e70affab..fa60dca35f 100644 --- a/app/ui/legacy/src/main/res/values-gd/strings.xml +++ b/app/ui/legacy/src/main/res/values-gd/strings.xml @@ -174,7 +174,7 @@ Cc: Bcc: Cha b’ urrainn dhuinn an ceanglachan a shàbhaladh. - + diff --git a/app/ui/legacy/src/main/res/values-gl/strings.xml b/app/ui/legacy/src/main/res/values-gl/strings.xml index b99a3ab706..0c92d468d6 100644 --- a/app/ui/legacy/src/main/res/values-gl/strings.xml +++ b/app/ui/legacy/src/main/res/values-gl/strings.xml @@ -183,7 +183,7 @@ Cc: Bcc: Incapaz de gardar o anexo. - + diff --git a/app/ui/legacy/src/main/res/values-hr/strings.xml b/app/ui/legacy/src/main/res/values-hr/strings.xml index 91de9739ad..30f24ade37 100644 --- a/app/ui/legacy/src/main/res/values-hr/strings.xml +++ b/app/ui/legacy/src/main/res/values-hr/strings.xml @@ -163,7 +163,7 @@ Cc: Bcc: Nije moguće spremiti privitak. - + diff --git a/app/ui/legacy/src/main/res/values-hu/strings.xml b/app/ui/legacy/src/main/res/values-hu/strings.xml index ede0cd8fdb..bb806ce25b 100644 --- a/app/ui/legacy/src/main/res/values-hu/strings.xml +++ b/app/ui/legacy/src/main/res/values-hu/strings.xml @@ -190,8 +190,8 @@ Másolat: Titkos másolat: Nem lehet elmenteni a mellékletet. - - -> + + -> %s + diff --git a/app/ui/legacy/src/main/res/values-in/strings.xml b/app/ui/legacy/src/main/res/values-in/strings.xml index 4c08208a59..eba4eceed6 100644 --- a/app/ui/legacy/src/main/res/values-in/strings.xml +++ b/app/ui/legacy/src/main/res/values-in/strings.xml @@ -172,7 +172,7 @@ Cc: Bcc: Tidak dapat menyimpan lampiran. - + diff --git a/app/ui/legacy/src/main/res/values-is/strings.xml b/app/ui/legacy/src/main/res/values-is/strings.xml index 2d3063415e..9bbb88e1b1 100644 --- a/app/ui/legacy/src/main/res/values-is/strings.xml +++ b/app/ui/legacy/src/main/res/values-is/strings.xml @@ -191,8 +191,8 @@ Afrit: Falið afrit: Tókst ekki að vista viðhengi - - "til " + + til %s + diff --git a/app/ui/legacy/src/main/res/values-it/strings.xml b/app/ui/legacy/src/main/res/values-it/strings.xml index 9a3f42bb76..62f4597862 100644 --- a/app/ui/legacy/src/main/res/values-it/strings.xml +++ b/app/ui/legacy/src/main/res/values-it/strings.xml @@ -193,8 +193,8 @@ Cc: Ccn: Impossibile salvare l\'allegato. - - "a " + + a %s + diff --git a/app/ui/legacy/src/main/res/values-iw/strings.xml b/app/ui/legacy/src/main/res/values-iw/strings.xml index ad02ed0c96..81a3902efa 100644 --- a/app/ui/legacy/src/main/res/values-iw/strings.xml +++ b/app/ui/legacy/src/main/res/values-iw/strings.xml @@ -177,7 +177,7 @@ מחק קובץ מצורף ל: עותק: - + diff --git a/app/ui/legacy/src/main/res/values-ja/strings.xml b/app/ui/legacy/src/main/res/values-ja/strings.xml index 75650b7c90..7b3c5f5582 100644 --- a/app/ui/legacy/src/main/res/values-ja/strings.xml +++ b/app/ui/legacy/src/main/res/values-ja/strings.xml @@ -188,7 +188,7 @@ Cc: Bcc: 添付ファイルを保存できません。 - + + diff --git a/app/ui/legacy/src/main/res/values-ko/strings.xml b/app/ui/legacy/src/main/res/values-ko/strings.xml index c5163b27f0..cee6760e43 100644 --- a/app/ui/legacy/src/main/res/values-ko/strings.xml +++ b/app/ui/legacy/src/main/res/values-ko/strings.xml @@ -174,7 +174,7 @@ 참조: Bcc: 첨부파일을 저장할 수 없음 - + diff --git a/app/ui/legacy/src/main/res/values-lt/strings.xml b/app/ui/legacy/src/main/res/values-lt/strings.xml index 6e87c36760..774f336b0b 100644 --- a/app/ui/legacy/src/main/res/values-lt/strings.xml +++ b/app/ui/legacy/src/main/res/values-lt/strings.xml @@ -194,8 +194,8 @@ Cc: Bcc: Nepavyko išsaugoti priedo. - - "kam " + + kam %s + diff --git a/app/ui/legacy/src/main/res/values-lv/strings.xml b/app/ui/legacy/src/main/res/values-lv/strings.xml index ac51d72bf4..bf945df182 100644 --- a/app/ui/legacy/src/main/res/values-lv/strings.xml +++ b/app/ui/legacy/src/main/res/values-lv/strings.xml @@ -193,8 +193,8 @@ pat %d vairāk Cc: Neredzamais: Nevar saglabāt pielikumu. - - "kam " + + kam %s + diff --git a/app/ui/legacy/src/main/res/values-ml/strings.xml b/app/ui/legacy/src/main/res/values-ml/strings.xml index 4ea210a9e6..9f67fcb0a7 100644 --- a/app/ui/legacy/src/main/res/values-ml/strings.xml +++ b/app/ui/legacy/src/main/res/values-ml/strings.xml @@ -184,7 +184,7 @@ Cc: Bcc: അറ്റാച്ചുമെന്റ് സേവ് ചെയ്യാനായില്ല. - + diff --git a/app/ui/legacy/src/main/res/values-nb/strings.xml b/app/ui/legacy/src/main/res/values-nb/strings.xml index aac226befc..3e7259a779 100644 --- a/app/ui/legacy/src/main/res/values-nb/strings.xml +++ b/app/ui/legacy/src/main/res/values-nb/strings.xml @@ -169,7 +169,7 @@ til %d flere Kopi: Blindkopi: Klarte ikke lagre vedlegg - + diff --git a/app/ui/legacy/src/main/res/values-nl/strings.xml b/app/ui/legacy/src/main/res/values-nl/strings.xml index ea9c88cf84..65cf24d2db 100644 --- a/app/ui/legacy/src/main/res/values-nl/strings.xml +++ b/app/ui/legacy/src/main/res/values-nl/strings.xml @@ -190,8 +190,8 @@ CC: BCC: Kan bijlage niet opslaan. - - "aan " + + aan %s + diff --git a/app/ui/legacy/src/main/res/values-pl/strings.xml b/app/ui/legacy/src/main/res/values-pl/strings.xml index 76b86a01f2..ad3b7c0108 100644 --- a/app/ui/legacy/src/main/res/values-pl/strings.xml +++ b/app/ui/legacy/src/main/res/values-pl/strings.xml @@ -195,8 +195,8 @@ Wysłane z urządzenia Android za pomocą K-9 Mail. Proszę wybaczyć moją zwi DW: UDW: Nie można zapisać załącznika. - - "do " + + do %s + diff --git a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml index c3ef2eb492..6b0336b28b 100644 --- a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml +++ b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml @@ -192,8 +192,8 @@ Cc: Cco: Não foi possível salvar o anexo. - - "para " + + para %s + diff --git a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml index 814bcaca2d..f4d35af52f 100644 --- a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml +++ b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml @@ -193,8 +193,8 @@ Cc: Bcc: Não foi possível guardar o anexo - - "para " + + para %s + diff --git a/app/ui/legacy/src/main/res/values-ro/strings.xml b/app/ui/legacy/src/main/res/values-ro/strings.xml index ac47210e56..0e41f471ed 100644 --- a/app/ui/legacy/src/main/res/values-ro/strings.xml +++ b/app/ui/legacy/src/main/res/values-ro/strings.xml @@ -193,8 +193,8 @@ cel mult încă %d Cc: Bcc: Nu se poate salva atașamentul. - - "la " + + la %s + diff --git a/app/ui/legacy/src/main/res/values-ru/strings.xml b/app/ui/legacy/src/main/res/values-ru/strings.xml index cae0fcee43..17f527e72c 100644 --- a/app/ui/legacy/src/main/res/values-ru/strings.xml +++ b/app/ui/legacy/src/main/res/values-ru/strings.xml @@ -194,8 +194,8 @@ Копия: Скрытая копия: Не получается сохранить вложение. - - "для " + + для %s + diff --git a/app/ui/legacy/src/main/res/values-sk/strings.xml b/app/ui/legacy/src/main/res/values-sk/strings.xml index 3cc945ad7d..4e9274fd36 100644 --- a/app/ui/legacy/src/main/res/values-sk/strings.xml +++ b/app/ui/legacy/src/main/res/values-sk/strings.xml @@ -174,7 +174,7 @@ Kópia: Skrytá kópia (Bcc): Prílohu sa nepodarilo uložiť. - + diff --git a/app/ui/legacy/src/main/res/values-sl/strings.xml b/app/ui/legacy/src/main/res/values-sl/strings.xml index 67d8fa51c2..71786f5921 100644 --- a/app/ui/legacy/src/main/res/values-sl/strings.xml +++ b/app/ui/legacy/src/main/res/values-sl/strings.xml @@ -194,8 +194,8 @@ dodatnih %d sporočil Kp: Skp: Priloge ni mogoče shraniti. - - "za " + + za %s + diff --git a/app/ui/legacy/src/main/res/values-sq/strings.xml b/app/ui/legacy/src/main/res/values-sq/strings.xml index 60392caac8..cbfe68e312 100644 --- a/app/ui/legacy/src/main/res/values-sq/strings.xml +++ b/app/ui/legacy/src/main/res/values-sq/strings.xml @@ -191,8 +191,8 @@ Cc: Bcc: S\’arrihet të ruhet bashkëngjitje - - "për " + + për %s + diff --git a/app/ui/legacy/src/main/res/values-sr/strings.xml b/app/ui/legacy/src/main/res/values-sr/strings.xml index 5a71f6d5fb..a436048198 100644 --- a/app/ui/legacy/src/main/res/values-sr/strings.xml +++ b/app/ui/legacy/src/main/res/values-sr/strings.xml @@ -173,7 +173,7 @@ Коп: СКоп: Не могу да сачувам прилог. - + diff --git a/app/ui/legacy/src/main/res/values-sv/strings.xml b/app/ui/legacy/src/main/res/values-sv/strings.xml index 2c814062b7..e47fb9ff64 100644 --- a/app/ui/legacy/src/main/res/values-sv/strings.xml +++ b/app/ui/legacy/src/main/res/values-sv/strings.xml @@ -191,8 +191,8 @@ Kopia: Blindkopia: Det går inte att spara bilaga. - - "till " + + till %s + diff --git a/app/ui/legacy/src/main/res/values-tr/strings.xml b/app/ui/legacy/src/main/res/values-tr/strings.xml index 554d4f7054..a6e55f65c4 100644 --- a/app/ui/legacy/src/main/res/values-tr/strings.xml +++ b/app/ui/legacy/src/main/res/values-tr/strings.xml @@ -188,7 +188,7 @@ Bilgi: Gizli Kopya: Eklenti kaydedilemedi - + diff --git a/app/ui/legacy/src/main/res/values-uk/strings.xml b/app/ui/legacy/src/main/res/values-uk/strings.xml index 56bef84ce8..efff762606 100644 --- a/app/ui/legacy/src/main/res/values-uk/strings.xml +++ b/app/ui/legacy/src/main/res/values-uk/strings.xml @@ -195,8 +195,8 @@ Копія: Прихована копія: Не вдалося зберегти вкладення. - - "для " + + для %s + diff --git a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml index 8974ab327b..8c4d27bdcf 100644 --- a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml +++ b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml @@ -188,8 +188,8 @@ 抄送: 密送: 无法保存附件。 - - + + %s + diff --git a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml index c5ce6ccb63..c85159a9c3 100644 --- a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml +++ b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml @@ -188,8 +188,8 @@ 副本: 密件副本: 無法存檔附件。 - - + + %s + diff --git a/app/ui/legacy/src/main/res/values/strings.xml b/app/ui/legacy/src/main/res/values/strings.xml index 8e1e5b9430..4b2a76e048 100644 --- a/app/ui/legacy/src/main/res/values/strings.xml +++ b/app/ui/legacy/src/main/res/values/strings.xml @@ -229,8 +229,8 @@ Bcc: Unable to save attachment. - - "to " + + to %s + diff --git a/app/ui/legacy/src/test/java/com/fsck/k9/ui/messageview/RecipientLayoutCreatorTest.kt b/app/ui/legacy/src/test/java/com/fsck/k9/ui/messageview/RecipientLayoutCreatorTest.kt index b9d1a3c31e..14a306ab73 100644 --- a/app/ui/legacy/src/test/java/com/fsck/k9/ui/messageview/RecipientLayoutCreatorTest.kt +++ b/app/ui/legacy/src/test/java/com/fsck/k9/ui/messageview/RecipientLayoutCreatorTest.kt @@ -24,7 +24,7 @@ class RecipientLayoutCreatorTest : RobolectricTest() { private val recipientLayoutCreator = RecipientLayoutCreator( textMeasure = textMeasure, maxNumberOfRecipientNames = 5, - recipientsPrefix = "to ", + recipientsFormat = "to %s", additionalRecipientSpacing = 1, additionalRecipientsPrefix = "+", ) -- GitLab From a79f2e818159f82aaf151fb81890e696b859d463 Mon Sep 17 00:00:00 2001 From: Thomas Braccia Date: Thu, 21 Sep 2023 12:59:59 -0400 Subject: [PATCH 92/94] Update flag icon to have content description --- .../java/com/fsck/k9/ui/messagelist/MessageListAdapter.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListAdapter.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListAdapter.kt index 87e179690c..17263d9d0e 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListAdapter.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messagelist/MessageListAdapter.kt @@ -387,6 +387,11 @@ class MessageListAdapter internal constructor( if (appearance.stars) { holder.star.isSelected = isStarred + holder.starClickArea.contentDescription = if (isStarred) { + res.getString(R.string.unflag_action) + } else { + res.getString(R.string.flag_action) + } } holder.uniqueId = uniqueId if (appearance.showContactPicture && holder.contactPicture.isVisible) { -- GitLab From 97f18d313ce3d01816e6271123f2123b48d0d9bd Mon Sep 17 00:00:00 2001 From: cketti Date: Wed, 4 Oct 2023 12:31:42 +0200 Subject: [PATCH 93/94] Version 6.711 --- app/k9mail/build.gradle.kts | 4 ++-- app/ui/legacy/src/main/res/raw/changelog_master.xml | 10 ++++++++++ fastlane/metadata/android/en-US/changelogs/37011.txt | 8 ++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/37011.txt diff --git a/app/k9mail/build.gradle.kts b/app/k9mail/build.gradle.kts index bcf60947b3..047b77b54f 100644 --- a/app/k9mail/build.gradle.kts +++ b/app/k9mail/build.gradle.kts @@ -50,8 +50,8 @@ android { applicationId = "com.fsck.k9" testApplicationId = "com.fsck.k9.tests" - versionCode = 37010 - versionName = "6.711-SNAPSHOT" + versionCode = 37011 + versionName = "6.711" // Keep in sync with the resource string array "supported_languages" resourceConfigurations.addAll( diff --git a/app/ui/legacy/src/main/res/raw/changelog_master.xml b/app/ui/legacy/src/main/res/raw/changelog_master.xml index 711d63e965..d0327107cf 100644 --- a/app/ui/legacy/src/main/res/raw/changelog_master.xml +++ b/app/ui/legacy/src/main/res/raw/changelog_master.xml @@ -5,6 +5,16 @@ Locale-specific versions are kept in res/raw-/changelog.xml. --> + + Simplified the app icon so it can be a vector drawable + Improved screen reader experience in various places + Improved logging on failing settings import + Improved display of some HTML messages + Changed background color in message view and compose screens when using dark theme + Fixed OAuth 2.0 with Yahoo and AOL + Fixed display issues when rendering a message/rfc822 inline part + Updated translations + Fixed bug where accounts using OAuth weren't set up properly in K-9 Mail 6.709 Moved "Show only subscribed folders" setting to "Folders" section diff --git a/fastlane/metadata/android/en-US/changelogs/37011.txt b/fastlane/metadata/android/en-US/changelogs/37011.txt new file mode 100644 index 0000000000..d9d64e4ebd --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/37011.txt @@ -0,0 +1,8 @@ +- Simplified the app icon so it can be a vector drawable +- Improved screen reader experience in various places +- Improved logging on failing settings import +- Improved display of some HTML messages +- Changed background color in message view and compose screens when using dark theme +- Fixed OAuth 2.0 with Yahoo and AOL +- Fixed display issues when rendering a message/rfc822 inline part +- Updated translations -- GitLab From 8b9abf2bcc94bab0691a75e28a68a44ebdc2c351 Mon Sep 17 00:00:00 2001 From: cketti Date: Wed, 4 Oct 2023 13:53:37 +0200 Subject: [PATCH 94/94] Fix F-Droid build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fdroidserver contains code to strip signing config blocks from `build.gradle[.kts]` files. That code also removed the assignment inside the `let` lambda. This in turn lead to Gradle failing the compilation of the Kotlin script because the argument `releaseSigningConfig` was unused 😞 Adding the "F-Droid hack" comment in this line prevents fdroidserver's regular expression from matching and removing this line. --- app/k9mail/build.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/k9mail/build.gradle.kts b/app/k9mail/build.gradle.kts index 047b77b54f..1ea6b0c25e 100644 --- a/app/k9mail/build.gradle.kts +++ b/app/k9mail/build.gradle.kts @@ -84,7 +84,9 @@ android { buildTypes { release { signingConfigs.findByName("release")?.let { releaseSigningConfig -> - signingConfig = releaseSigningConfig + // The comment in the line below is necessary to prevent F-Droid's build tools from breaking our Gradle + // config when stripping the signing config. + signingConfig = releaseSigningConfig // F-Droid hack } isMinifyEnabled = true -- GitLab