Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
e
os
AccountManager
Commits
0d57747a
Commit
0d57747a
authored
Apr 13, 2022
by
Vincent Bourgmayer
🎼
Browse files
Merge branch 'master' into '123-allowMeteredConnection-eDrive'
# Conflicts: # app/src/main/AndroidManifest.xml
parents
ee040bdd
f8cb13bd
Pipeline
#178199
passed with stage
in 1 minute and 57 seconds
Changes
12
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
0d57747a
...
...
@@ -5,6 +5,7 @@ stages:
before_script
:
-
git submodule update --init --recursive
-
echo email.key $EMAIL_KEY >> local.properties
-
export GRADLE_USER_HOME=$(pwd)/.gradle
-
chmod +x ./gradlew
...
...
app/build.gradle
View file @
0d57747a
...
...
@@ -33,6 +33,7 @@ android {
multiDexEnabled
true
// >64k methods for Android 4.4
buildConfigField
"String"
,
"userAgent"
,
"\"DAVx5\""
buildConfigField
"String"
,
"EMAIL_KEY"
,
"\"${emailKey()}\""
// when using this, make sure that notification icons are real bitmaps
vectorDrawables
.
useSupportLibrary
=
true
...
...
@@ -161,3 +162,13 @@ dependencies {
testImplementation
'junit:junit:4.12'
testImplementation
"com.squareup.okhttp3:mockwebserver:${versions.okhttp}"
}
def
emailKey
()
{
Properties
properties
=
new
Properties
()
try
{
properties
.
load
(
project
.
rootProject
.
file
(
'local.properties'
).
newDataInputStream
())
}
catch
(
ignored
)
{
// Ignore
}
return
properties
.
getProperty
(
"email.key"
,
"invalid"
)
}
app/src/main/AndroidManifest.xml
View file @
0d57747a
...
...
@@ -44,6 +44,16 @@
android:label=
"@string/app_name"
android:theme=
"@style/AppTheme"
tools:ignore=
"UnusedAttribute"
>
<activity
android:name=
".ui.setup.CreateAccountActivity"
android:label=
"@string/create_account"
android:exported=
"true"
android:parentActivityName=
".ui.AccountsActivity"
>
<intent-filter>
<action
android:name=
"${applicationId}.ui.setup.CreateAccountActivity"
/>
<category
android:name=
"android.intent.category.DEFAULT"
/>
</intent-filter>
</activity>
<service
android:name=
".DavService"
/>
...
...
@@ -216,7 +226,7 @@
<intent-filter>
<action
android:name=
"android.content.SyncAdapter"
/>
</intent-filter>
<meta-data
android:name=
"android.content.SyncAdapter"
android:resource=
"@xml/eelo_sync_calendars"
/>
...
...
@@ -350,7 +360,7 @@
android:name=
"android.provider.CONTACTS_STRUCTURE"
android:resource=
"@xml/contacts"
/>
</service>
<!-- account type "Google" -->
<service
android:name=
".syncadapter.GoogleAccountAuthenticatorService"
...
...
app/src/main/java/foundation/e/accountmanager/ui/setup/CreateAccountActivity.kt
0 → 100644
View file @
0d57747a
/*
* Copyright © ECORP SAS 2022.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package
foundation.e.accountmanager.ui.setup
import
android.os.Bundle
import
androidx.appcompat.app.AppCompatActivity
import
foundation.e.accountmanager.R
class
CreateAccountActivity
:
AppCompatActivity
()
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
setContentView
(
R
.
layout
.
activity_create_account
)
supportFragmentManager
.
beginTransaction
().
apply
{
replace
(
R
.
id
.
content
,
SendInviteFragment
())
commit
()
}
}
}
\ No newline at end of file
app/src/main/java/foundation/e/accountmanager/ui/setup/InviteSuccessfulFragment.kt
0 → 100644
View file @
0d57747a
/*
* Copyright © ECORP SAS 2022.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package
foundation.e.accountmanager.ui.setup
import
android.accounts.AccountManager
import
android.accounts.AccountManagerCallback
import
android.app.Activity.RESULT_OK
import
android.content.Intent
import
android.os.Bundle
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.widget.Button
import
android.widget.TextView
import
androidx.appcompat.app.AppCompatActivity
import
androidx.fragment.app.Fragment
import
foundation.e.accountmanager.R
class
InviteSuccessfulFragment
:
Fragment
()
{
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?
):
View
?
{
(
activity
as
AppCompatActivity
?)
?.
supportActionBar
?.
hide
()
return
inflater
.
inflate
(
R
.
layout
.
fragment_invite_successful
,
container
,
false
)
}
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
val
instructions
=
view
.
findViewById
<
TextView
>(
R
.
id
.
instructions
)
val
formattedText
=
view
.
context
.
getText
(
R
.
string
.
instructions
)
instructions
.
text
=
formattedText
view
.
findViewById
<
Button
>(
R
.
id
.
sign_in
).
setOnClickListener
{
try
{
activity
?.
let
{
val
accountManager
=
AccountManager
.
get
(
it
)
accountManager
.
addAccount
(
"e.foundation.webdav.eelo"
,
null
,
null
,
null
,
it
,
AccountManagerCallback
<
Bundle
?>
{
activity
?.
setResult
(
RESULT_OK
,
Intent
())
activity
?.
finish
()
},
null
)
}
}
catch
(
e
:
Exception
)
{
}
}
view
.
findViewById
<
Button
>(
R
.
id
.
sign_in_later
).
setOnClickListener
{
activity
?.
setResult
(
RESULT_OK
,
Intent
())
activity
?.
finish
()
}
}
}
\ No newline at end of file
app/src/main/java/foundation/e/accountmanager/ui/setup/SendInviteFragment.kt
0 → 100644
View file @
0d57747a
/*
* Copyright © ECORP SAS 2022.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package
foundation.e.accountmanager.ui.setup
import
android.accounts.AccountManager
import
android.accounts.AccountManagerCallback
import
android.app.Activity
import
android.content.Context
import
android.content.Intent
import
android.net.ConnectivityManager
import
android.os.Bundle
import
android.text.Editable
import
android.text.TextWatcher
import
androidx.fragment.app.Fragment
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.widget.Button
import
android.widget.EditText
import
android.widget.Toast
import
com.google.android.material.dialog.MaterialAlertDialogBuilder
import
com.google.android.material.textfield.TextInputLayout
import
foundation.e.accountmanager.BuildConfig
import
foundation.e.accountmanager.R
import
okhttp3.*
import
java.io.IOException
import
java.math.BigInteger
import
java.security.MessageDigest
class
SendInviteFragment
:
Fragment
()
{
private
var
email
=
""
private
val
key
=
BuildConfig
.
EMAIL_KEY
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?
):
View
?
{
return
inflater
.
inflate
(
R
.
layout
.
fragment_send_invite
,
container
,
false
)
}
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
val
emailTextField
=
view
.
findViewById
<
EditText
>(
R
.
id
.
emailId
)
val
emailTextLayout
=
view
.
findViewById
<
TextInputLayout
>(
R
.
id
.
emailId_layout
)
val
sendButton
=
view
.
findViewById
<
Button
>(
R
.
id
.
send_button
)
emailTextField
.
addTextChangedListener
(
object
:
TextWatcher
{
override
fun
beforeTextChanged
(
p0
:
CharSequence
?,
p1
:
Int
,
p2
:
Int
,
p3
:
Int
)
{
}
override
fun
onTextChanged
(
p0
:
CharSequence
?,
p1
:
Int
,
p2
:
Int
,
p3
:
Int
)
{
if
(
p0
.
toString
().
trim
().
isNotEmpty
())
{
sendButton
.
isEnabled
=
true
sendButton
.
setBackgroundColor
(
resources
.
getColor
(
R
.
color
.
create_account_input_enabled_color
))
emailTextLayout
.
boxStrokeColor
=
resources
.
getColor
(
R
.
color
.
create_account_input_enabled_color
)
emailTextLayout
.
hintTextColor
=
resources
.
getColorStateList
(
R
.
color
.
create_account_input_enabled_color
)
}
else
{
sendButton
.
isEnabled
=
false
sendButton
.
setBackgroundColor
(
resources
.
getColor
(
R
.
color
.
create_account_input_disabled_color
))
emailTextLayout
.
boxStrokeColor
=
resources
.
getColor
(
R
.
color
.
create_account_input_disabled_color
)
emailTextLayout
.
hintTextColor
=
resources
.
getColorStateList
(
R
.
color
.
create_account_input_disabled_color
)
}
}
override
fun
afterTextChanged
(
p0
:
Editable
?)
{
}
})
sendButton
.
setOnClickListener
{
email
=
emailTextField
.
text
.
toString
()
if
(
isNetworkAvailable
())
{
createAccount
()
}
else
{
Toast
.
makeText
(
context
,
R
.
string
.
no_internet_toast
,
Toast
.
LENGTH_LONG
).
show
()
}
}
}
private
fun
createAccount
()
{
val
client
=
OkHttpClient
()
val
userAgentKey
=
"User-Agent"
val
userAgentValue
=
"Java 11 HttpClient Bot"
val
contentKey
=
"Content-Type"
val
contentValue
=
"application/x-www-form-urlencoded"
val
inviteUrl
=
"https://welcome.ecloud.global/process_email_invite.php"
val
formBody
=
FormBody
.
Builder
()
.
add
(
"email"
,
email
)
.
add
(
"check"
,
secretCode
())
.
build
()
val
request
=
Request
.
Builder
()
.
post
(
formBody
)
.
header
(
userAgentKey
,
userAgentValue
)
.
addHeader
(
contentKey
,
contentValue
)
.
url
(
inviteUrl
)
.
build
()
client
.
newCall
(
request
).
enqueue
(
object
:
Callback
{
override
fun
onFailure
(
call
:
Call
,
e
:
IOException
)
{
e
.
printStackTrace
()
}
override
fun
onResponse
(
call
:
Call
,
response
:
Response
)
{
if
(!
response
.
isSuccessful
)
throw
IOException
(
"Unexpected code $response"
)
val
stringCode
=
response
.
body
()
?.
string
()
activity
?.
runOnUiThread
{
stringCode
?.
let
{
getIntCode
(
it
)
}
?.
let
{
handleErrorCode
(
it
)
}
}
}
})
}
private
fun
secretCode
():
String
{
val
md
:
MessageDigest
=
MessageDigest
.
getInstance
(
"MD5"
)
return
BigInteger
(
1
,
md
.
digest
((
email
+
key
).
toByteArray
())).
toString
(
16
).
padStart
(
32
,
'0'
)
}
private
fun
getIntCode
(
stringCode
:
String
):
Int
{
val
trimedResult
:
String
=
stringCode
.
trim
()
val
errorCode
=
trimedResult
.
substring
(
trimedResult
.
lastIndexOf
(
":"
)
+
1
,
trimedResult
.
length
-
1
)
return
errorCode
.
toInt
()
}
private
fun
handleErrorCode
(
intCode
:
Int
)
{
when
(
intCode
)
{
100
->
{
requireFragmentManager
().
beginTransaction
()
.
replace
(
R
.
id
.
content
,
InviteSuccessfulFragment
())
.
commit
()
}
200
->
{
activity
?.
let
{
MaterialAlertDialogBuilder
(
it
,
R
.
style
.
CustomAlertDialogStyle
)
.
setIcon
(
R
.
drawable
.
ic_error
)
.
setTitle
(
R
.
string
.
user_exists_dialog_title
)
.
setMessage
(
R
.
string
.
user_exists_dialog_message
)
.
setPositiveButton
(
R
.
string
.
skip_button
)
{
_
,
_
->
activity
?.
setResult
(
Activity
.
RESULT_OK
,
Intent
())
activity
?.
finish
()
}
.
setNegativeButton
(
R
.
string
.
login_button
)
{
_
,
_
->
try
{
val
accountManager
=
AccountManager
.
get
(
it
)
accountManager
.
addAccount
(
"e.foundation.webdav.eelo"
,
null
,
null
,
null
,
it
,
AccountManagerCallback
<
Bundle
?>
{
activity
?.
setResult
(
Activity
.
RESULT_OK
,
Intent
())
activity
?.
finish
()
},
null
)
}
catch
(
e
:
Exception
)
{
}
}
.
show
()
}
}
300
->
{
activity
?.
let
{
val
emailField
=
it
.
findViewById
<
TextInputLayout
>(
R
.
id
.
emailId_layout
)
emailField
.
error
=
getString
(
R
.
string
.
emailid_error
)
}
}
else
->
{
activity
?.
let
{
MaterialAlertDialogBuilder
(
it
,
R
.
style
.
CustomAlertDialogStyle
)
.
setIcon
(
R
.
drawable
.
ic_error
)
.
setTitle
(
R
.
string
.
error_dialog_title
)
.
setMessage
(
R
.
string
.
error_dialog_message
)
.
setPositiveButton
(
R
.
string
.
skip_button
)
{
_
,
_
->
activity
?.
setResult
(
Activity
.
RESULT_OK
,
Intent
())
activity
?.
finish
()
}
.
setNegativeButton
(
R
.
string
.
try_again_button
)
{
_
,
_
->
createAccount
()
}
.
show
()
}
}
}
}
private
fun
isNetworkAvailable
():
Boolean
{
val
connectivityManager
=
activity
?.
getSystemService
(
Context
.
CONNECTIVITY_SERVICE
)
as
ConnectivityManager
val
activeNetworkInfo
=
connectivityManager
.
activeNetworkInfo
return
activeNetworkInfo
!=
null
&&
activeNetworkInfo
.
isConnectedOrConnecting
}
}
\ No newline at end of file
app/src/main/res/drawable/ic_error.xml
0 → 100644
View file @
0d57747a
<!--
~ Copyright © ECORP SAS 2022.
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<vector
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:width=
"24dp"
android:height=
"24dp"
android:viewportWidth=
"24.0"
android:viewportHeight=
"24.0"
>
<path
android:fillColor=
"#99000000"
android:pathData=
"M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm1,15h-2v-2h2v2zm0,-4h-2V7h2v6z"
/>
</vector>
app/src/main/res/layout/activity_create_account.xml
0 → 100644
View file @
0d57747a
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright © ECORP SAS 2022.
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
tools:context=
".ui.setup.CreateAccountActivity"
>
<FrameLayout
android:id=
"@+id/content"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
app/src/main/res/layout/fragment_invite_successful.xml
0 → 100644
View file @
0d57747a
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright © ECORP SAS 2022.
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@android:color/white"
>
<LinearLayout
android:id=
"@+id/successful_box"
android:background=
"#f6f6f6"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"24dp"
android:orientation=
"horizontal"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
>
<ImageView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:src=
"@drawable/ic_done"
app:tint=
"#4EA719"
android:layout_marginStart=
"24dp"
android:layout_marginTop=
"28dp"
android:layout_marginBottom=
"28dp"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:textColor=
"@*android:color/bright_foreground_holo_light"
android:textSize=
"13sp"
android:layout_marginStart=
"17dp"
android:layout_marginEnd=
"24dp"
android:layout_marginTop=
"24dp"
android:layout_marginBottom=
"24dp"
android:text=
"@string/invitation_sent"
/>
</LinearLayout>
<TextView
android:id=
"@+id/instructions_heading"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"48dp"
android:layout_marginStart=
"24dp"
android:textSize=
"20sp"
android:textColor=
"@*android:color/bright_foreground_holo_light"
android:text=
"@string/instructions_heading"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/successful_box"
/>
<TextView
android:id=
"@+id/instructions"
android:textSize=
"16sp"
android:textColor=
"@color/instructions_text"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"24dp"
android:layout_marginStart=
"24dp"
android:layout_marginEnd=
"24dp"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/instructions_heading"
/>
<Button
android:id=
"@+id/sign_in"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginBottom=
"16dp"
android:layout_marginStart=
"16dp"
android:layout_marginEnd=
"16dp"
app:backgroundTint=
"@*android:color/accent_material_light"
android:textColor=
"@android:color/white"
android:text=
"@string/sign_in_button"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/instructions"
app:layout_constraintBottom_toBottomOf=
"parent"
/>
<Button
android:id=
"@+id/sign_in_later"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"@string/setup_later_button"
android:textColor=
"@*android:color/accent_material_light"
style=
"@style/Widget.MaterialComponents.Button.TextButton"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/sign_in"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/fragment_send_invite.xml
0 → 100644
View file @
0d57747a
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright © ECORP SAS 2022.
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<TextView
android:id=
"@+id/heading"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"25dp"
android:paddingStart=
"24dp"
android:paddingEnd=
"24dp"
android:textSize=
"16sp"
android:textColor=
"@*android:color/bright_foreground_holo_light"
android:text=
"@string/send_invite_heading"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<com.google.android.material.textfield.TextInputLayout
android:id=
"@+id/emailId_layout"
style=
"@style/edittext_holder_style"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:paddingStart=
"17dp"
android:paddingEnd=
"17dp"
android:layout_marginTop=
"25dp"
android:theme=
"@style/edittext_holder_theme"
app:hintTextColor=
"@color/create_account_input_disabled_color"
app:errorEnabled=
"true"
app:boxStrokeColor=
"@color/create_account_input_disabled_color"
app:layout_constraintStart_toStartOf=
"@id/heading"
app:layout_constraintTop_toBottomOf=
"@id/heading"
>
<com.google.android.material.textfield.TextInputEditText
android:id=
"@+id/emailId"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:hint=
"@string/email_hint"
android:inputType=
"textEmailAddress"
android:textColor=
"@color/primaryTextColor"
/>
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id=
"@+id/send_button"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
app:backgroundTint=
"@color/create_account_button_disabled_color"
android:enabled=
"false"
android:text=
"@string/send_button"
android:textColor=
"@android:color/white"
android:layout_marginTop=
"17dp"
android:layout_marginEnd=
"16dp"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/emailId_layout"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
app/src/main/res/values/colors.xml
0 → 100644
View file @
0d57747a
<!--
~ Copyright © ECORP SAS 2022.
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<resources>
<color
name=
"create_account_button_enabled_color"
>
@*android:color/accent_material_light
</color>
<color
name=
"create_account_button_disabled_color"
>
#61000000
</color>
<color
name=
"create_account_input_enabled_color"
>
@*android:color/accent_material_light
</color>
<color
name=
"create_account_input_disabled_color"
>
#61000000
</color>
<color
name=
"instructions_text"
>
#BD000000
</color>