Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Sign in / Register
Toggle navigation
FreshRSS-Android
Project
Project
Details
Activity
Releases
Cycle Analytics
Insights
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Locked Files
Issues
25
Issues
25
List
Boards
Labels
Service Desk
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Christophe Henry
FreshRSS-Android
Commits
29f57a8a
Commit
29f57a8a
authored
Apr 15, 2019
by
Christophe Henry
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix #57: http:// scheme is reduced to http:/
parent
5a249c76
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
160 additions
and
93 deletions
+160
-93
app/build.gradle
app/build.gradle
+0
-1
app/src/main/java/fr/chenry/android/freshrss/activities/LoginActivity.kt
...va/fr/chenry/android/freshrss/activities/LoginActivity.kt
+32
-31
app/src/main/java/fr/chenry/android/freshrss/store/api/Endpoints.kt
...in/java/fr/chenry/android/freshrss/store/api/Endpoints.kt
+1
-21
app/src/main/java/fr/chenry/android/freshrss/utils/InstanceUrl.kt
...main/java/fr/chenry/android/freshrss/utils/InstanceUrl.kt
+51
-0
app/src/main/res/layout/activity_login.xml
app/src/main/res/layout/activity_login.xml
+33
-35
app/src/main/res/layout/fragment_subscription_article_detail.xml
.../main/res/layout/fragment_subscription_article_detail.xml
+2
-2
app/src/main/res/values/strings.xml
app/src/main/res/values/strings.xml
+5
-0
app/src/main/res/values/styles.xml
app/src/main/res/values/styles.xml
+10
-3
app/src/test/java/fr/chenry/android/freshrss/store/api/InstanceUrlTest.kt
...a/fr/chenry/android/freshrss/store/api/InstanceUrlTest.kt
+26
-0
No files found.
app/build.gradle
View file @
29f57a8a
...
@@ -22,7 +22,6 @@ android {
...
@@ -22,7 +22,6 @@ android {
}
}
}
}
}
}
sourceSets
{
sourceSets
{
androidTest
.
assets
.
srcDirs
+=
files
(
schema_location
)
androidTest
.
assets
.
srcDirs
+=
files
(
schema_location
)
}
}
...
...
app/src/main/java/fr/chenry/android/freshrss/activities/LoginActivity.kt
View file @
29f57a8a
...
@@ -8,24 +8,24 @@ import android.os.Bundle
...
@@ -8,24 +8,24 @@ import android.os.Bundle
import
android.view.View
import
android.view.View
import
android.view.inputmethod.EditorInfo
import
android.view.inputmethod.EditorInfo
import
android.view.inputmethod.InputMethodManager
import
android.view.inputmethod.InputMethodManager
import
android.widget.TextView
import
android.widget.*
import
android.widget.AdapterView.OnItemSelectedListener
import
androidx.appcompat.app.AppCompatActivity
import
androidx.appcompat.app.AppCompatActivity
import
androidx.core.widget.addTextChangedListener
import
androidx.core.widget.addTextChangedListener
import
fr.chenry.android.freshrss.FreshRSSApplication
import
fr.chenry.android.freshrss.R
import
fr.chenry.android.freshrss.R
import
fr.chenry.android.freshrss.store.database.FreshRSSDabatabase
import
fr.chenry.android.freshrss.store.Store
import
fr.chenry.android.freshrss.store.Store
import
fr.chenry.android.freshrss.store.api.Endpoints
import
fr.chenry.android.freshrss.utils.*
import
fr.chenry.android.freshrss.utils.*
import
kotlinx.android.synthetic.main.activity_login.*
import
kotlinx.android.synthetic.main.activity_login.*
import
nl.komponents.kovenant.ui.failUi
import
nl.komponents.kovenant.ui.failUi
import
nl.komponents.kovenant.ui.successUi
import
nl.komponents.kovenant.ui.successUi
import
java.util.
*
import
java.util.
Properties
/**
/**
* A login screen that offers login via email/password.
* A login screen that offers login via email/password.
*/
*/
class
LoginActivity
:
AppCompatActivity
()
{
class
LoginActivity
:
AppCompatActivity
()
{
private
lateinit
var
instanceUrl
:
InstanceUrl
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
super
.
onCreate
(
savedInstanceState
)
...
@@ -40,18 +40,28 @@ class LoginActivity: AppCompatActivity() {
...
@@ -40,18 +40,28 @@ class LoginActivity: AppCompatActivity() {
})
})
email_sign_in_button
.
setOnClickListener
{
attemptLogin
()}
email_sign_in_button
.
setOnClickListener
{
attemptLogin
()}
instanceUrl
=
InstanceUrl
(
InstanceUrl
.
authorizedProtocols
[
0
],
resources
.
getString
(
R
.
string
.
instance_exemple
))
activity_login_protocol_selection
.
adapter
=
ArrayAdapter
<
String
>(
this
,
android
.
R
.
layout
.
simple_spinner_item
,
InstanceUrl
.
authorizedProtocols
)
t
ry
{
T
ry
{
val
properties
=
Properties
()
val
properties
=
Properties
()
properties
.
load
(
baseContext
.
assets
.
open
(
"config.properties"
))
properties
.
load
(
baseContext
.
assets
.
open
(
"config.properties"
))
instance
.
setText
(
properties
.
getProperty
(
"instance"
))
instanceUrl
=
InstanceUrl
.
parse
(
properties
.
getProperty
(
"instance"
))
instance
.
setText
(
instanceUrl
.
base
)
val
protocolIdx
=
InstanceUrl
.
authorizedProtocols
.
indexOf
(
instanceUrl
.
protocole
)
activity_login_protocol_selection
.
setSelection
(
if
(
protocolIdx
>=
0
)
protocolIdx
else
0
)
login
.
setText
(
properties
.
getProperty
(
"login"
))
login
.
setText
(
properties
.
getProperty
(
"login"
))
password
.
setText
(
properties
.
getProperty
(
"password"
))
password
.
setText
(
properties
.
getProperty
(
"password"
))
}
catch
(
_
:
Throwable
)
{
}
}
computeInstanceURLHint
()
computeInstanceURLHint
()
instance
.
addTextChangedListener
{
computeInstanceURLHint
()}
instance
.
addTextChangedListener
{
computeInstanceURLHint
()}
activity_login_protocol_selection
.
onItemSelectedListener
=
object
:
OnItemSelectedListener
{
override
fun
onNothingSelected
(
parent
:
AdapterView
<
*
>?)
=
computeInstanceURLHint
()
override
fun
onItemSelected
(
parent
:
AdapterView
<
*
>?,
view
:
View
?,
position
:
Int
,
id
:
Long
)
=
computeInstanceURLHint
()
}
resetErrors
()
resetErrors
()
instance
.
requestFocus
()
instance
.
requestFocus
()
}
}
...
@@ -59,14 +69,19 @@ class LoginActivity: AppCompatActivity() {
...
@@ -59,14 +69,19 @@ class LoginActivity: AppCompatActivity() {
private
fun
attemptLogin
()
{
private
fun
attemptLogin
()
{
resetErrors
()
resetErrors
()
var
cancel
=
false
var
focusView
:
View
?
=
null
if
(
instanceUrl
.
isMalformed
)
{
instance
.
error
=
getString
(
R
.
string
.
instance_url_malformed
)
focusView
=
instance
cancel
=
true
}
// Store values at the time of the login attempt.
// Store values at the time of the login attempt.
val
instanceStr
=
instance
.
text
.
toString
()
val
loginStr
=
login
.
text
.
toString
()
val
loginStr
=
login
.
text
.
toString
()
val
passwordStr
=
password
.
text
.
toString
()
val
passwordStr
=
password
.
text
.
toString
()
var
cancel
=
false
var
focusView
:
View
?
=
null
// Check for a valid password, if the user entered one.
// Check for a valid password, if the user entered one.
if
(
passwordStr
.
isBlank
())
{
if
(
passwordStr
.
isBlank
())
{
password
.
error
=
getString
(
R
.
string
.
error_invalid_password
)
password
.
error
=
getString
(
R
.
string
.
error_invalid_password
)
...
@@ -85,7 +100,7 @@ class LoginActivity: AppCompatActivity() {
...
@@ -85,7 +100,7 @@ class LoginActivity: AppCompatActivity() {
focusView
?.
requestFocus
()
focusView
?.
requestFocus
()
}
else
{
}
else
{
showProgress
(
true
)
showProgress
(
true
)
Store
.
login
(
instance
Str
,
loginStr
,
passwordStr
)
successUi
{
Store
.
login
(
instance
Url
.
toString
()
,
loginStr
,
passwordStr
)
successUi
{
startActivity
(
Intent
(
this
,
MainActivity
::
class
.
java
))
startActivity
(
Intent
(
this
,
MainActivity
::
class
.
java
))
finish
()
finish
()
}
failUi
{
}
failUi
{
...
@@ -100,21 +115,10 @@ class LoginActivity: AppCompatActivity() {
...
@@ -100,21 +115,10 @@ class LoginActivity: AppCompatActivity() {
val
instanceStr
=
instance
.
text
.
toString
().
let
{
val
instanceStr
=
instance
.
text
.
toString
().
let
{
if
(
it
.
isBlank
())
resources
.
getString
(
R
.
string
.
instance_exemple
)
else
it
if
(
it
.
isBlank
())
resources
.
getString
(
R
.
string
.
instance_exemple
)
else
it
}
}
reified_instance_url
.
text
=
instanceStr
.
cleanUrlSlashes
().
replace
(
"/$"
.
toRegex
(),
""
)
if
(!
Endpoints
.
hasProtocol
(
instanceStr
))
{
protocol_default
.
text
=
Endpoints
.
defaultProtocol
protocol_default
.
visibility
=
View
.
VISIBLE
}
else
{
protocol_default
.
visibility
=
View
.
GONE
}
if
(!
Endpoints
.
hasApiEndpoint
(
instanceStr
))
{
val
protocole
=
activity_login_protocol_selection
.
selectedItem
.
toString
()
api_endpoint
.
text
=
Endpoints
.
apiEndpoint
val
instanceUrl
=
InstanceUrl
(
protocole
,
instanceStr
)
api_endpoint
.
visibility
=
View
.
VISIBLE
reified_instance_url
.
text
=
instanceUrl
.
toSpanString
()
}
else
{
api_endpoint
.
visibility
=
View
.
GONE
}
}
}
private
fun
resetErrors
()
{
private
fun
resetErrors
()
{
...
@@ -134,10 +138,7 @@ class LoginActivity: AppCompatActivity() {
...
@@ -134,10 +138,7 @@ class LoginActivity: AppCompatActivity() {
}
}
private
fun
showProgress
(
show
:
Boolean
)
{
private
fun
showProgress
(
show
:
Boolean
)
{
login_progress_text
.
text
=
resources
.
getString
(
login_progress_text
.
text
=
resources
.
getString
(
R
.
string
.
login_progress_text
,
instanceUrl
.
toString
())
R
.
string
.
login_progress_text
,
Endpoints
.
computeApiUrl
(
instance
.
text
.
toString
())
)
val
shortAnimTime
=
resources
.
getInteger
(
android
.
R
.
integer
.
config_shortAnimTime
).
toLong
()
val
shortAnimTime
=
resources
.
getInteger
(
android
.
R
.
integer
.
config_shortAnimTime
).
toLong
()
...
...
app/src/main/java/fr/chenry/android/freshrss/store/api/Endpoints.kt
View file @
29f57a8a
package
fr.chenry.android.freshrss.store.api
package
fr.chenry.android.freshrss.store.api
import
fr.chenry.android.freshrss.utils.cleanUrlSlashes
class
Endpoints
(
private
val
base
:
String
)
{
class
Endpoints
(
base
:
String
)
{
private
val
base
=
computeApiUrl
(
base
)
val
loginEndpoint
=
"${this.base}/accounts/ClientLogin"
val
loginEndpoint
=
"${this.base}/accounts/ClientLogin"
val
tokenEndpoint
=
"${this.base}/reader/api/0/token"
val
tokenEndpoint
=
"${this.base}/reader/api/0/token"
val
subscriptionEndpoint
=
"${this.base}/reader/api/0/subscription/list"
val
subscriptionEndpoint
=
"${this.base}/reader/api/0/subscription/list"
...
@@ -12,21 +9,4 @@ class Endpoints(base: String) {
...
@@ -12,21 +9,4 @@ class Endpoints(base: String) {
val
tagEndpoint
=
"${this.base}/reader/api/0/tag/list"
val
tagEndpoint
=
"${this.base}/reader/api/0/tag/list"
val
unreadItemsEndpoint
=
"${this.base}/reader/api/0/stream/contents/user/-/state/com.google/reading-list"
val
unreadItemsEndpoint
=
"${this.base}/reader/api/0/stream/contents/user/-/state/com.google/reading-list"
val
editTagEnpoint
=
"${this.base}/reader/api/0/edit-tag"
val
editTagEnpoint
=
"${this.base}/reader/api/0/edit-tag"
companion
object
{
const
val
defaultProtocol
=
"https://"
const
val
apiEndpoint
=
"/api/greader.php"
fun
computeApiUrl
(
fromUrl
:
String
):
String
{
return
when
(
hasProtocol
(
fromUrl
)
to
hasApiEndpoint
(
fromUrl
))
{
(
false
to
false
)
->
"$defaultProtocol${"
$
fromUrl
$
apiEndpoint
".cleanUrlSlashes()}"
(
false
to
true
)
->
"$defaultProtocol${fromUrl.cleanUrlSlashes()}"
(
true
to
false
)
->
"$fromUrl$apiEndpoint"
else
->
fromUrl
}
}
fun
hasProtocol
(
url
:
String
)
=
url
.
matches
(
"^https?://.*$"
.
toRegex
())
fun
hasApiEndpoint
(
url
:
String
)
=
url
.
endsWith
(
apiEndpoint
)
}
}
}
\ No newline at end of file
app/src/main/java/fr/chenry/android/freshrss/utils/InstanceUrl.kt
0 → 100644
View file @
29f57a8a
package
fr.chenry.android.freshrss.utils
import
android.text.SpannableStringBuilder
import
androidx.core.content.ContextCompat
import
androidx.core.text.bold
import
androidx.core.text.color
import
fr.chenry.android.freshrss.FreshRSSApplication
import
fr.chenry.android.freshrss.R
import
java.net.URL
class
InstanceUrl
(
val
protocole
:
String
,
base
:
String
)
{
val
isMalformed
:
Boolean
val
base
=
base
.
replace
(
".*://"
.
toRegex
(),
""
)
.
replace
(
"//+"
.
toRegex
(),
"/"
)
.
replace
(
"/$"
.
toRegex
(),
""
)
private
val
hasApiEndpoint
:
Boolean
=
this
.
base
.
endsWith
(
apiEndpoint
)
private
val
endpoint
:
String
=
if
(
hasApiEndpoint
)
""
else
apiEndpoint
init
{
isMalformed
=
Try
{
URL
(
"$protocole${this.base}"
)}.
getOrNull
()
==
null
}
fun
toSpanString
():
CharSequence
=
SpannableStringBuilder
().
apply
{
val
urlString
=
base
.
let
{
if
(
hasApiEndpoint
)
it
else
it
.
replace
(
apiEndpoint
,
""
)}
color
(
ContextCompat
.
getColor
(
FreshRSSApplication
.
context
,
R
.
color
.
grey
))
{
append
(
protocole
)}
bold
{
append
(
urlString
)}
if
(!
hasApiEndpoint
)
color
(
ContextCompat
.
getColor
(
FreshRSSApplication
.
context
,
R
.
color
.
grey
))
{
append
(
apiEndpoint
)}
}
override
fun
toString
():
String
=
"$protocole$base$endpoint"
companion
object
{
private
const
val
apiEndpoint
=
"/api/greader.php"
val
authorizedProtocols
=
arrayOf
(
"https://"
,
"http://"
)
fun
parse
(
url
:
String
):
InstanceUrl
{
"(.*://)"
.
toPattern
().
matcher
(
url
).
let
{
if
(
it
.
find
())
{
val
protocol
=
it
.
group
(
0
)
if
(
authorizedProtocols
.
contains
(
protocol
))
return
InstanceUrl
(
protocol
,
url
)
}
}
return
InstanceUrl
(
authorizedProtocols
[
0
],
url
)
}
}
}
\ No newline at end of file
app/src/main/res/layout/activity_login.xml
View file @
29f57a8a
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
xmlns:
app=
"http://schemas.android.com/apk/res-auto"
xmlns:
tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_height=
"match_parent"
android:gravity=
"center"
android:gravity=
"center"
...
@@ -24,53 +24,51 @@
...
@@ -24,53 +24,51 @@
android:visibility=
"visible"
android:visibility=
"visible"
>
>
<
com.google.android.material.textfield.TextInput
Layout
<
Linear
Layout
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
android:layout_height=
"wrap_content"
android:orientation=
"horizontal"
<EditText
>
android:id=
"@+id/instance"
<Spinner
android:layout_width=
"match_parent"
android:id=
"@+id/activity_login_protocol_selection"
android:layout_width=
"wrap_content"
android:layout_height=
"match_parent"
android:entries=
"@array/connection_options"
android:dropDownWidth=
"wrap_content"
android:spinnerMode=
"dropdown"
/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:hint=
"@string/prompt_instance"
android:layout_weight=
"100"
>
android:maxLines=
"1"
<EditText
android:singleLine=
"true"
android:id=
"@+id/instance"
android:inputType=
"textUri"
android:layout_width=
"match_parent"
android:autoLink=
"web|none"
/>
android:layout_height=
"wrap_content"
</com.google.android.material.textfield.TextInputLayout>
android:hint=
"@string/prompt_instance"
android:maxLines=
"1"
android:singleLine=
"true"
android:inputType=
"textUri"
android:autoLink=
"web|none"
/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<LinearLayout
<LinearLayout
android:orientation=
"horizontal"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"
match_par
ent"
android:layout_height=
"
wrap_cont
ent"
android:paddingLeft=
"6dp"
android:paddingLeft=
"6dp"
android:paddingRight=
"6dp"
android:paddingRight=
"6dp"
android:layout_marginBottom=
"@dimen/activity_horizontal_margin"
>
android:paddingTop=
"@dimen/subscription_section_h_padding"
android:paddingBottom=
"@dimen/subscription_section_h_padding"
<TextView
android:orientation=
"horizontal"
android:id=
"@+id/protocol_default"
>
android:text=
"@string/protocol_default"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:textColor=
"@color/grey"
/>
<TextView
<TextView
android:id=
"@+id/reified_instance_url"
android:id=
"@+id/reified_instance_url"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:text=
"@string/instance_exemple"
android:text=
"@string/instance_exemple"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:textColor=
"@color/black"
/>
<TextView
android:id=
"@+id/api_endpoint"
android:text=
"@string/api_endpoint"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:textColor=
"@color/grey"
/>
/>
</LinearLayout>
</LinearLayout>
<com.google.android.material.textfield.TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
android:layout_height=
"wrap_content"
>
...
...
app/src/main/res/layout/fragment_subscription_article_detail.xml
View file @
29f57a8a
...
@@ -20,13 +20,13 @@
...
@@ -20,13 +20,13 @@
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"@string/share"
android:text=
"@string/share"
android:layout_margin=
"16dp"
android:layout_margin=
"16dp"
app:icon=
"?attr/actionModeShareDrawable"
/>
app:icon=
"?attr/actionModeShareDrawable"
android:theme=
"@style/FabAppTheme"
/>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id=
"@+id/fab_open_browser"
android:id=
"@+id/fab_open_browser"
android:layout_width=
"wrap_content"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_margin=
"16dp"
android:layout_margin=
"16dp"
android:text=
"@string/original_page"
android:text=
"@string/original_page"
app:icon=
"@drawable/ic_web_black_24dp"
/>
app:icon=
"@drawable/ic_web_black_24dp"
android:theme=
"@style/FabAppTheme"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
</FrameLayout>
\ No newline at end of file
app/src/main/res/values/strings.xml
View file @
29f57a8a
<resources>
<resources>
<!-- Do not translate -->
<!-- Do not translate -->
<string
name=
"app_name"
>
FreshRSS
</string>
<string
name=
"app_name"
>
FreshRSS
</string>
<string-array
name=
"connection_options"
>
<item>
https://
</item>
<item>
http://
</item>
</string-array>
<string
name=
"prompt_login"
>
Login
</string>
<string
name=
"prompt_login"
>
Login
</string>
<string
name=
"prompt_password"
>
Password
</string>
<string
name=
"prompt_password"
>
Password
</string>
...
@@ -74,4 +78,5 @@
...
@@ -74,4 +78,5 @@
<string
name=
"subscription_categories"
>
Categories
</string>
<string
name=
"subscription_categories"
>
Categories
</string>
<string
name=
"share_article"
>
Share article of %s
</string>
<string
name=
"share_article"
>
Share article of %s
</string>
<string
name=
"this_feed"
>
this feed
</string>
<string
name=
"this_feed"
>
this feed
</string>
<string
name=
"instance_url_malformed"
>
This URL is malformed
</string>
</resources>
</resources>
app/src/main/res/values/styles.xml
View file @
29f57a8a
<resources>
<resources>
<!-- Base application theme. -->
<!-- Base application theme. -->
<style
name=
"AppTheme"
parent=
"Theme.
MaterialComponents
.Light.DarkActionBar"
>
<style
name=
"AppTheme"
parent=
"Theme.
AppCompat
.Light.DarkActionBar"
>
<!-- Customize your theme here. -->
<!-- Customize your theme here. -->
<item
name=
"colorPrimary"
>
@color/color_primary
</item>
<item
name=
"colorPrimary"
>
@color/color_primary
</item>
<item
name=
"colorPrimaryDark"
>
@color/color_primary_dark
</item>
<item
name=
"colorPrimaryDark"
>
@color/color_primary_dark
</item>
...
@@ -11,11 +11,18 @@
...
@@ -11,11 +11,18 @@
<item
name=
"windowActionBar"
>
false
</item>
<item
name=
"windowActionBar"
>
false
</item>
<item
name=
"windowNoTitle"
>
true
</item>
<item
name=
"windowNoTitle"
>
true
</item>
</style>
</style>
<style
name=
"AppTheme.AppBarOverlay"
parent=
"ThemeOverlay.
MaterialComponents
.Dark.ActionBar"
/>
<style
name=
"AppTheme.AppBarOverlay"
parent=
"ThemeOverlay.
AppCompat
.Dark.ActionBar"
/>
<style
name=
"AppTheme.PopupOverlay"
parent=
"ThemeOverlay.
MaterialComponents
.Light"
/>
<style
name=
"AppTheme.PopupOverlay"
parent=
"ThemeOverlay.
AppCompat
.Light"
/>
<style
name=
"AppTheme.ExtendedFloatingActionButton"
parent=
"Widget.MaterialComponents.ExtendedFloatingActionButton"
>
<style
name=
"AppTheme.ExtendedFloatingActionButton"
parent=
"Widget.MaterialComponents.ExtendedFloatingActionButton"
>
<item
name=
"backgroundTint"
>
@color/color_primary
</item>
<item
name=
"backgroundTint"
>
@color/color_primary
</item>
<item
name=
"android:textColor"
>
@color/design_default_color_on_primary
</item>
<item
name=
"android:textColor"
>
@color/design_default_color_on_primary
</item>
<item
name=
"iconTint"
>
@color/design_default_color_on_primary
</item>
<item
name=
"iconTint"
>
@color/design_default_color_on_primary
</item>
</style>
</style>
<style
name=
"FabAppTheme"
parent=
"Theme.MaterialComponents.Light.DarkActionBar"
>
<!-- Customize your theme here. -->
<item
name=
"colorPrimary"
>
@color/color_primary
</item>
<item
name=
"colorPrimaryDark"
>
@color/color_primary_dark
</item>
<item
name=
"colorAccent"
>
@color/color_accent
</item>
<item
name=
"extendedFloatingActionButtonStyle"
>
@style/AppTheme.ExtendedFloatingActionButton
</item>
</style>
</resources>
</resources>
app/src/test/java/fr/chenry/android/freshrss/store/api/InstanceUrlTest.kt
0 → 100644
View file @
29f57a8a
package
fr.chenry.android.freshrss.store.api
import
fr.chenry.android.freshrss.utils.InstanceUrl
import
fr.chenry.android.freshrss.utils.InstanceUrl.Companion
import
org.junit.*
import
org.junit.Assert.*
class
InstanceUrlTest
{
@Test
fun
testComputeApiUrl
()
{
assertEquals
(
"https://your-instance.com/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com"
).
toString
())
assertEquals
(
"https://your-instance.com/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com/"
).
toString
())
assertEquals
(
"https://your-instance.com/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com//"
).
toString
())
assertEquals
(
"https://your-instance.com/p/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com/p"
).
toString
())
assertEquals
(
"https://your-instance.com/p/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com/p/"
).
toString
())
assertEquals
(
"https://your-instance.com/p/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com/p//"
).
toString
())
assertEquals
(
"https://your-instance.com/p/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com//p//"
).
toString
())
assertEquals
(
"https://your-instance.com/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com/api/greader.php"
).
toString
())
assertEquals
(
"https://your-instance.com/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com/api/greader.php/"
).
toString
())
assertEquals
(
"https://your-instance.com/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com//api/greader.php/"
).
toString
())
assertEquals
(
"https://your-instance.com/p/api/greader.php"
,
InstanceUrl
.
parse
(
"your-instance.com/p/api/greader.php"
).
toString
())
assertEquals
(
"http://your-instance.com/p/api/greader.php"
,
InstanceUrl
.
parse
(
"http://your-instance.com/p/api/greader.php"
).
toString
())
assertEquals
(
"http://your-instance.com/p/api/greader.php"
,
InstanceUrl
.
parse
(
"http://your-instance.com//p/api/greader.php"
).
toString
())
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment