Compare commits

...

30 Commits

Author SHA1 Message Date
Amine Louveau
ab9c46f0eb Update 'CHANGELOG.md' 2023-02-21 15:00:37 +00:00
Amine Louveau
aa799d2ca8 Changelog for v123020523 [CI SKIP] 2023-02-21 14:49:14 +00:00
Amine Louveau
177c978474 fix: Git changelog. 2023-02-21 14:05:32 +00:00
Amine Louveau
39b9991413 Changelog for v123020522 [CI SKIP] 2023-02-21 13:25:11 +00:00
Amine Louveau
b303f110f1 fix: still fixing changelog versions. 2023-02-21 12:59:38 +00:00
Amine Louveau
f851941a6a Changelog for v123020521 [CI SKIP] 2023-02-21 11:31:18 +00:00
Amine Louveau
a313552976 fix: change changelog version on release. 2023-02-21 11:20:43 +00:00
aminecmi
6ac97ed3fe Changelog for v123020491 [CI SKIP] 2023-02-20 09:39:40 +00:00
aminecmi
d583b937b7 fix: Fixed acra bug reporting. 2023-02-20 10:29:00 +01:00
aminecmi
15b9a2d935 Changelog for v123010301 [CI SKIP] 2023-02-18 20:01:03 +00:00
aminecmi
5a8ce15961 Chore: acra config. 2023-02-18 20:38:06 +01:00
e1c64cef46 Changelog for v123010281 [CI SKIP] 2023-01-30 19:55:23 +00:00
ee064f3cb4 improvement: Improve right to left support (#130)
Co-authored-by: davidoskky <davidoskky@hidden.hidden>
Co-committed-by: davidoskky <davidoskky@hidden.hidden>
2023-01-29 12:55:28 +00:00
3e46e2ff29 Changelog for v123010261 [CI SKIP] 2023-01-28 10:57:06 +00:00
f28e702549 feat: Handle public instances (#126)
Co-authored-by: davidoskky <davidoskky@hidden.hidden>
Co-committed-by: davidoskky <davidoskky@hidden.hidden>
2023-01-28 10:25:28 +00:00
aminecmi
fc31a4399c ci: Pull request should trigger ci. 2023-01-28 11:23:00 +01:00
Amine Louveau
9b23053b66 fix: Complete the disconnection before redirecting to the login screen
Reviewed-on: https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/pulls/129
2023-01-28 11:20:19 +01:00
389a04d250 Complete the disconnection before redirecting to the login screen 2023-01-27 14:21:33 +01:00
Amine Louveau
40e1d1478b Changelog for v123010241 [CI SKIP] 2023-01-26 10:55:43 +00:00
Amine Louveau
2154ff3c33 Merge pull request 'feat: swipe down to close images' (#122) from davidoskky/ReaderForSelfoss-multiplatform:swipe_down into master
Reviewed-on: https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/pulls/122
2023-01-26 10:42:15 +00:00
2245565f95 Remove unnecessary definition 2023-01-25 21:25:32 +01:00
014858f06b Remove unused import 2023-01-25 20:40:20 +01:00
3f1f86a78e Adjust the image closing animation 2023-01-25 10:34:03 +01:00
a549169a7c Add a dark hue to the underlying article when swiping to close images 2023-01-25 10:27:38 +01:00
be7cae365a Rename activity style to avoid interferences 2023-01-25 02:09:41 +01:00
cef3b2e593 Adapt the style of the image activity to the rest of the application 2023-01-25 01:54:35 +01:00
ae927ebc57 Resolve issues when swiping down to close images 2023-01-25 00:46:43 +01:00
ddc72d85b0 Close the image fragment only if the image has been dragged down 2023-01-21 16:37:25 +01:00
68bbf5b2d3 Animate swipe down to close images 2023-01-20 16:36:52 +01:00
2b6659f4ec Swipe down to close images 2023-01-11 22:28:14 +01:00
33 changed files with 625 additions and 332 deletions

View File

@ -35,6 +35,7 @@ steps:
trigger: trigger:
event: event:
- push - push
- pull_request
--- ---
kind: pipeline kind: pipeline
@ -47,13 +48,14 @@ steps:
commands: commands:
- apt-get update && apt-get install -y git - apt-get update && apt-get install -y git
- git fetch --tags -p - git fetch --tags -p
- PREV=$(git describe --tags --abbrev=0)
- ./build.sh --publish --from-ci
- git remote add pushing https://$GITEA_USR:$GITEA_PASS@gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform.git
- VER=$(git describe --tags --abbrev=0) - VER=$(git describe --tags --abbrev=0)
- CHANGELOG=$(git log $VER..HEAD --pretty="- %s") - CHANGELOG=$(git log $PREV..HEAD --pretty="- %s")
- echo "**$VER**\n\n$CHANGELOG\n\n--------------------------------------------------------------------\n\n$(cat CHANGELOG.md)" > CHANGELOG.md - echo "**$VER**\n\n$CHANGELOG\n\n--------------------------------------------------------------------\n\n$(cat CHANGELOG.md)" > CHANGELOG.md
- git add CHANGELOG.md - git add CHANGELOG.md
- git commit -m "Changelog for $VER [CI SKIP]" - git commit -m "Changelog for $VER [CI SKIP]"
- ./build.sh --publish --from-ci
- git remote add pushing https://$GITEA_USR:$GITEA_PASS@gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform.git
- git push pushing master - git push pushing master
- git push pushing --tags - git push pushing --tags
environment: environment:

View File

@ -1,3 +1,52 @@
**v123020523**
- fix: Git changelog.
--------------------------------------------------------------------
**v123020491**
- fix: Fixed acra bug reporting.
--------------------------------------------------------------------
**v123010301**
- Chore: acra config.
--------------------------------------------------------------------
**v123010281**
- improvement: Improve right to left support (#130) Co-authored-by: davidoskky <davidoskky@hidden.hidden> Co-committed-by: davidoskky <davidoskky@hidden.hidden>
--------------------------------------------------------------------
**v123010261**
- feat: Handle public instances (#126) Co-authored-by: davidoskky <davidoskky@hidden.hidden> Co-committed-by: davidoskky <davidoskky@hidden.hidden>
- ci: Pull request should trigger ci.
- fix: Complete the disconnection before redirecting to the login screen
- Complete the disconnection before redirecting to the login screen
--------------------------------------------------------------------
**v123010241**
- Merge pull request 'feat: swipe down to close images' (#122) from davidoskky/ReaderForSelfoss-multiplatform:swipe_down into master
- Remove unnecessary definition
- Remove unused import
- Adjust the image closing animation
- Add a dark hue to the underlying article when swiping to close images
- Rename activity style to avoid interferences
- Adapt the style of the image activity to the rest of the application
- Resolve issues when swiping down to close images
- Close the image fragment only if the image has been dragged down
- Animate swipe down to close images
- Swipe down to close images
--------------------------------------------------------------------
**v123010041** **v123010041**
- Merge pull request 'scroll-tag-filters' (#124) from scroll-tag-filters into master - Merge pull request 'scroll-tag-filters' (#124) from scroll-tag-filters into master

View File

@ -115,7 +115,6 @@ dependencies {
implementation(project(":shared")) implementation(project(":shared"))
implementation("com.google.android.material:material:1.5.0") implementation("com.google.android.material:material:1.5.0")
implementation("androidx.appcompat:appcompat:1.4.1") implementation("androidx.appcompat:appcompat:1.4.1")
implementation("androidx.constraintlayout:constraintlayout:2.1.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0")
implementation("androidx.preference:preference-ktx:1.1.1") implementation("androidx.preference:preference-ktx:1.1.1")
@ -131,7 +130,7 @@ dependencies {
implementation("androidx.cardview:cardview:1.0.0") implementation("androidx.cardview:cardview:1.0.0")
implementation("androidx.annotation:annotation:1.3.0") implementation("androidx.annotation:annotation:1.3.0")
implementation("androidx.work:work-runtime-ktx:2.7.1") implementation("androidx.work:work-runtime-ktx:2.7.1")
implementation("androidx.constraintlayout:constraintlayout:2.1.3") implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("org.jsoup:jsoup:1.14.3") implementation("org.jsoup:jsoup:1.14.3")
//multidex //multidex

View File

@ -70,7 +70,8 @@
android:name=".ReaderActivity"> android:name=".ReaderActivity">
</activity> </activity>
<activity <activity
android:name=".ImageActivity"> android:name=".ImageActivity"
android:theme="@style/Theme.AppCompat.ImageActivity">
</activity> </activity>
<meta-data android:name="android.webkit.WebView.MetricsOptOut" <meta-data android:name="android.webkit.WebView.MetricsOptOut"

View File

@ -36,6 +36,7 @@ import com.ashokvarma.bottomnavigation.TextBadgeItem
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.kodein.di.DIAware import org.kodein.di.DIAware
import org.kodein.di.android.closestDI import org.kodein.di.android.closestDI
import org.kodein.di.instance import org.kodein.di.instance
@ -114,10 +115,16 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
} }
} }
val swipeDirs = if (appSettingsService.getPublicAccess()) {
0
} else {
ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
}
val simpleItemTouchCallback = val simpleItemTouchCallback =
object : ItemTouchHelper.SimpleCallback( object : ItemTouchHelper.SimpleCallback(
0, 0,
ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT swipeDirs
) { ) {
override fun getSwipeDirs( override fun getSwipeDirs(
recyclerView: RecyclerView, recyclerView: RecyclerView,
@ -510,6 +517,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater val inflater = menuInflater
inflater.inflate(R.menu.home_menu, menu) inflater.inflate(R.menu.home_menu, menu)
if (appSettingsService.getPublicAccess()) {
menu.removeItem(R.id.readAll)
menu.removeItem(R.id.action_sources)
}
val searchItem = menu.findItem(R.id.action_search) val searchItem = menu.findItem(R.id.action_search)
val searchView = searchItem.getActionView() as SearchView val searchView = searchItem.getActionView() as SearchView
@ -588,12 +599,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
return true return true
} }
R.id.action_disconnect -> { R.id.action_disconnect -> {
CoroutineScope(Dispatchers.Main).launch { runBlocking {
repository.logout() repository.logout()
} }
this@HomeActivity.finish()
val intent = Intent(this, LoginActivity::class.java) val intent = Intent(this, LoginActivity::class.java)
this.startActivity(intent) this.startActivity(intent)
finish()
return true return true
} }
R.id.action_settings -> { R.id.action_settings -> {

View File

@ -3,6 +3,7 @@ package bou.amine.apps.readerforselfossv2.android
import android.os.Bundle import android.os.Bundle
import android.view.MenuItem import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
@ -23,7 +24,6 @@ class ImageActivity : AppCompatActivity() {
setContentView(view) setContentView(view)
setSupportActionBar(binding.toolBar) setSupportActionBar(binding.toolBar)
supportActionBar?.setDisplayShowTitleEnabled(false)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
allImages = intent.getStringArrayListExtra("allImages") as ArrayList<String> allImages = intent.getStringArrayListExtra("allImages") as ArrayList<String>
@ -31,12 +31,35 @@ class ImageActivity : AppCompatActivity() {
binding.pager.adapter = ScreenSlidePagerAdapter(this) binding.pager.adapter = ScreenSlidePagerAdapter(this)
binding.pager.setCurrentItem(position, false) binding.pager.setCurrentItem(position, false)
val transitionListener = object : MotionLayout.TransitionListener {
override fun onTransitionStarted(motionLayout: MotionLayout?, startId: Int, endId: Int) {
// Nothing
}
override fun onTransitionChange(motionLayout: MotionLayout?, startId: Int, endId: Int, progress: Float
) {
// Nothing
}
override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
if (motionLayout?.currentState == binding.root.endState) {
onBackPressedDispatcher.onBackPressed()
overridePendingTransition(0, 0)
}
}
override fun onTransitionTrigger(motionLayout: MotionLayout?, triggerId: Int, positive: Boolean, progress: Float) {
// Nothing
}
}
binding.root.setTransitionListener(transitionListener)
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
android.R.id.home -> { android.R.id.home -> {
onBackPressed() onBackPressedDispatcher.onBackPressed()
return true return true
} }
} }

View File

@ -128,7 +128,7 @@ class LoginActivity : AppCompatActivity(), DIAware {
private fun goToMain() { private fun goToMain() {
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
repository.updateApiVersion() repository.updateApiInformation()
ACRA.errorReporter.putCustomData("SELFOSS_API_VERSION", appSettingsService.getApiVersion().toString()) ACRA.errorReporter.putCustomData("SELFOSS_API_VERSION", appSettingsService.getApiVersion().toString())
} }
val intent = Intent(this, HomeActivity::class.java) val intent = Intent(this, HomeActivity::class.java)

View File

@ -34,6 +34,7 @@ import org.kodein.di.*
class MyApp : MultiDexApplication(), DIAware { class MyApp : MultiDexApplication(), DIAware {
override val di by DI.lazy { override val di by DI.lazy {
bind<AppSettingsService>() with singleton { AppSettingsService(ACRA.isACRASenderServiceProcess()) }
import(networkModule) import(networkModule)
bind<DriverFactory>() with singleton { DriverFactory(applicationContext) } bind<DriverFactory>() with singleton { DriverFactory(applicationContext) }
bind<ReaderForSelfossDB>() with singleton { ReaderForSelfossDB(driverFactory.createDriver()) } bind<ReaderForSelfossDB>() with singleton { ReaderForSelfossDB(driverFactory.createDriver()) }
@ -130,8 +131,8 @@ class MyApp : MultiDexApplication(), DIAware {
httpSender { httpSender {
uri = uri =
"https://bugs.amine-louveau.fr/report" /*best guess, you may need to adjust this*/ "https://bugs.amine-louveau.fr/report" /*best guess, you may need to adjust this*/
basicAuthLogin = "LMTlLZuazADohTCm" basicAuthLogin = "qMEscjj89Gwt6cPR"
basicAuthPassword = "he6ghHp83F0PYPfh" basicAuthPassword = "Yo58QFlGzFaWlBzP"
httpMethod = HttpSender.Method.POST httpMethod = HttpSender.Method.POST
} }
} }

View File

@ -84,7 +84,7 @@ class ReaderActivity : AppCompatActivity(), DIAware {
} }
private fun readItem(item: SelfossModel.Item) { private fun readItem(item: SelfossModel.Item) {
if (appSettingsService.isMarkOnScrollEnabled()) { if (appSettingsService.isMarkOnScrollEnabled() && !appSettingsService.getPublicAccess()) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
repository.markAsRead(item) repository.markAsRead(item)
} }
@ -137,28 +137,34 @@ class ReaderActivity : AppCompatActivity(), DIAware {
inflater.inflate(R.menu.reader_menu, menu) inflater.inflate(R.menu.reader_menu, menu)
toolbarMenu = menu toolbarMenu = menu
if (allItems.isNotEmpty() && allItems[currentItem].starred) {
canRemoveFromFavorite()
} else {
canFavorite()
}
alignmentMenu() alignmentMenu()
binding.pager.registerOnPageChangeCallback( if (appSettingsService.getPublicAccess()) {
object : ViewPager2.OnPageChangeCallback() { menu.removeItem(R.id.star)
} else {
override fun onPageSelected(position: Int) { if (allItems.isNotEmpty() && allItems[currentItem].starred) {
super.onPageSelected(position) canRemoveFromFavorite()
} else {
if (allItems[position].starred) { canFavorite()
canRemoveFromFavorite()
} else {
canFavorite()
}
readItem(allItems[position])
}
} }
)
binding.pager.registerOnPageChangeCallback(
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
if (allItems[position].starred) {
canRemoveFromFavorite()
} else {
canFavorite()
}
readItem(allItems[position])
}
}
)
}
return true return true
} }
@ -177,7 +183,7 @@ class ReaderActivity : AppCompatActivity(), DIAware {
when (item.itemId) { when (item.itemId) {
android.R.id.home -> { android.R.id.home -> {
onBackPressed() onBackPressedDispatcher.onBackPressed()
return true return true
} }
R.id.star -> { R.id.star -> {

View File

@ -56,6 +56,10 @@ class ItemCardAdapter(
val itm = items[position] val itm = items[position]
binding.favButton.isSelected = itm.starred binding.favButton.isSelected = itm.starred
if (appSettingsService.getPublicAccess()) {
binding.favButton.visibility = View.GONE
}
binding.title.text = itm.title.getHtmlDecoded() binding.title.text = itm.title.getHtmlDecoded()
binding.title.setOnTouchListener(LinkOnTouchListener()) binding.title.setOnTouchListener(LinkOnTouchListener())

View File

@ -195,6 +195,9 @@ class ArticleFragment : Fragment(), DIAware {
private fun handleFloatingToolbar(): FloatingToolbar { private fun handleFloatingToolbar(): FloatingToolbar {
val floatingToolbar: FloatingToolbar = binding.floatingToolbar val floatingToolbar: FloatingToolbar = binding.floatingToolbar
if (appSettingsService.getPublicAccess()) {
floatingToolbar.setMenu(R.menu.reader_toolbar_no_read)
}
floatingToolbar.attachFab(fab) floatingToolbar.attachFab(fab)
floatingToolbar.background = ColorDrawable(resources.getColor(R.color.colorAccent)) floatingToolbar.background = ColorDrawable(resources.getColor(R.color.colorAccent))

View File

@ -1,13 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout <androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
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" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawerContainer" android:id="@+id/drawerContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context="bou.amine.apps.readerforselfossv2.android.HomeActivity"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
xmlns:app="http://schemas.android.com/apk/res-auto"> tools:context="bou.amine.apps.readerforselfossv2.android.HomeActivity">
<androidx.coordinatorlayout.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordLayout" android:id="@+id/coordLayout"
@ -28,12 +27,14 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar app:popupTheme="?attr/toolbarPopupTheme" android:theme="@style/ToolBarStyle" <androidx.appcompat.widget.Toolbar
android:id="@+id/toolBar" android:id="@+id/toolBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:theme="@style/ToolBarStyle"
app:popupTheme="?attr/toolbarPopupTheme"
/> />
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
@ -45,19 +46,19 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:background="?android:attr/windowBackground"
android:background="?android:attr/windowBackground"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/emptyText" android:id="@+id/emptyText"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:paddingTop="100dp" android:paddingTop="100dp"
android:text="@string/nothing_here" android:text="@string/nothing_here"
android:textAlignment="center" android:textAlignment="center"
android:textAppearance="@style/TextAppearance.AppCompat.Headline" android:textAppearance="@style/TextAppearance.AppCompat.Headline"
android:background="@android:color/transparent"
android:visibility="gone" /> android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
@ -69,7 +70,7 @@
android:paddingBottom="60dp" android:paddingBottom="60dp"
android:scrollbars="vertical" android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior" app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:listitem="@layout/list_item"/> tools:listitem="@layout/list_item" />
</LinearLayout> </LinearLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
@ -77,6 +78,7 @@
</LinearLayout> </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.ashokvarma.bottomnavigation.BottomNavigationBar <com.ashokvarma.bottomnavigation.BottomNavigationBar
android:id="@+id/bottomBar" android:id="@+id/bottomBar"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -1,33 +1,40 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
app:layoutDescription="@xml/image_close_scene">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout" android:id="@+id/appBarLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar <androidx.appcompat.widget.Toolbar android:theme="@style/ToolBarStyle"
android:id="@+id/toolBar" android:id="@+id/toolBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
/> />
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2 <androidx.core.widget.NestedScrollView
android:id="@+id/pager" android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent" android:fillViewport="true"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/appBarLayout">
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/appBarLayout" />
</androidx.constraintlayout.widget.ConstraintLayout> <androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.motion.widget.MotionLayout>

View File

@ -1,31 +1,30 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout 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" 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:orientation="vertical" android:orientation="vertical"
tools:context="bou.amine.apps.readerforselfossv2.android.LoginActivity"> tools:context="bou.amine.apps.readerforselfossv2.android.LoginActivity">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar app:popupTheme="?attr/toolbarPopupTheme" android:theme="@style/ToolBarStyle" <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:theme="@style/ToolBarStyle"
/> app:popupTheme="?attr/toolbarPopupTheme" />
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin" android:padding="@dimen/activity_horizontal_margin">
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<!-- Login progress --> <!-- Login progress -->
<ProgressBar <ProgressBar
android:id="@+id/loginProgress" android:id="@+id/loginProgress"
@ -33,67 +32,65 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:visibility="gone"/> android:visibility="gone" />
<ScrollView <LinearLayout
android:id="@+id/loginForm" android:id="@+id/loginForm"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout <EditText
android:id="@+id/urlView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:hint="@string/prompt_url"
android:imeOptions="actionUnspecified"
android:importantForAutofill="no"
android:inputType="textUri"
android:maxLines="1"
android:minHeight="48dp" />
<EditText <com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/urlView" android:id="@+id/withLogin"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/prompt_url" android:text="@string/withLoginSwitch"
android:imeOptions="actionUnspecified" android:textAlignment="viewStart" />
android:importantForAutofill="no"
android:inputType="textUri"
android:maxLines="1" />
<com.google.android.material.switchmaterial.SwitchMaterial <EditText
android:text="@string/withLoginSwitch" android:id="@+id/loginView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="wrap_content"
android:id="@+id/withLogin" android:autofillHints="username"
android:layout_weight="1"/> android:hint="@string/prompt_login"
android:inputType="text"
android:maxLines="1"
android:minHeight="48dp"
android:visibility="gone" />
<EditText <EditText
android:id="@+id/loginView" android:id="@+id/passwordView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autofillHints="username" android:autofillHints="password"
android:hint="@string/prompt_login" android:hint="@string/prompt_password"
android:inputType="text" android:inputType="textPassword"
android:maxLines="1" android:maxLines="1"
android:visibility="gone" /> android:minHeight="48dp"
android:visibility="gone" />
<EditText <Button
android:id="@+id/passwordView" android:id="@+id/signInButton"
android:layout_width="match_parent" style="?android:textAppearanceSmall"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:autofillHints="password" android:layout_height="wrap_content"
android:hint="@string/prompt_password" android:layout_marginTop="16dp"
android:inputType="textPassword" android:layout_marginBottom="16dp"
android:maxLines="1" android:text="@string/action_sign_in"
android:visibility="gone" /> android:textStyle="bold" />
<Button </LinearLayout>
android:id="@+id/signInButton"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:text="@string/action_sign_in"
android:textStyle="bold" />
</LinearLayout>
</ScrollView>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -24,7 +24,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:scrollbars="vertical" android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:listitem="@layout/source_list_item">
</androidx.recyclerview.widget.RecyclerView> </androidx.recyclerview.widget.RecyclerView>
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton

View File

@ -17,100 +17,83 @@
<androidx.appcompat.widget.Toolbar app:popupTheme="?attr/toolbarPopupTheme" android:theme="@style/ToolBarStyle" <androidx.appcompat.widget.Toolbar app:popupTheme="?attr/toolbarPopupTheme" android:theme="@style/ToolBarStyle"
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize" />
/>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:layout_height="match_parent"
android:layout_width="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:id="@+id/formContainer" android:id="@+id/formContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:visibility="gone" android:visibility="gone"
app:layout_constraintHorizontal_bias="1.0" app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintVertical_bias="0.0"> app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
<EditText <EditText
android:id="@+id/nameInput" android:id="@+id/nameInput"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minHeight="48dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:autofillHints="false" android:autofillHints="false"
android:ems="10"
android:hint="@string/add_source_hint_name" android:hint="@string/add_source_hint_name"
android:inputType="text" android:inputType="text"
android:textColorHint="?android:textColorPrimary" android:textColorHint="?android:textColorPrimary"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<EditText <EditText
android:id="@+id/sourceUri"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:inputType="textUri" android:minHeight="48dp"
android:ems="10"
android:id="@+id/sourceUri"
android:hint="@string/add_source_hint_url"
android:textColorHint="?android:textColorPrimary"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/nameInput" android:autofillHints="false"
app:layout_constraintRight_toRightOf="parent" android:hint="@string/add_source_hint_url"
android:inputType="textUri"
android:textColorHint="?android:textColorPrimary"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
android:autofillHints="false" /> app:layout_constraintTop_toBottomOf="@+id/nameInput" />
<EditText <EditText
android:id="@+id/tags"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ems="10" android:minHeight="48dp"
android:id="@+id/tags"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/sourceUri" android:autofillHints="false"
android:hint="@string/add_source_hint_tags" android:hint="@string/add_source_hint_tags"
android:textColorHint="?android:textColorPrimary"
android:inputType="text" android:inputType="text"
android:autofillHints="false" /> android:textColorHint="?android:textColorPrimary"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sourceUri" />
<Spinner <Spinner
android:layout_width="match_parent"
android:id="@+id/spoutsSpinner" android:id="@+id/spoutsSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/tags"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
android:layout_height="40dp"/> app:layout_constraintTop_toBottomOf="@+id/tags" />
<Button <Button
android:text="@string/add_source_save" android:id="@+id/saveBtn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/saveBtn"
android:elevation="5dp"
android:textColor="?android:textColorPrimary"
android:layout_marginEnd="16dp"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/spoutsSpinner" android:elevation="5dp"
android:text="@string/add_source_save"
android:textColor="?android:textColorPrimary"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="16dp" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintVertical_bias="0.0"/> app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/spoutsSpinner" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
@ -119,8 +102,6 @@
style="?android:attr/progressBarStyleLarge" style="?android:attr/progressBarStyleLarge"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"

View File

@ -1,18 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/card" android:id="@+id/card"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="8dp" android:layout_margin="8dp"
android:layout_marginRight="8dp" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="8dp" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0.62"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
card_view:cardElevation="2dp" card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true" card_view:cardUseCompatPadding="true"
@ -28,8 +24,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:cropToPadding="true" android:cropToPadding="true"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/background_splash" app:srcCompat="@drawable/background_splash"
card_view:layout_constraintBottom_toTopOf="@+id/constraintLayout" /> card_view:layout_constraintBottom_toTopOf="@+id/constraintLayout" />
@ -39,18 +35,17 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/itemImage"> app:layout_constraintTop_toBottomOf="@+id/itemImage">
<ImageView <ImageView
android:id="@+id/sourceImage" android:id="@+id/sourceImage"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/background_splash" /> app:srcCompat="@drawable/background_splash" />
@ -58,70 +53,58 @@
android:id="@+id/title" android:id="@+id/title"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_margin="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:gravity="start"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textStyle="bold"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
app:layout_constraintHorizontal_bias="0.0" android:textStyle="bold"
app:layout_constraintLeft_toRightOf="@+id/sourceImage" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintStart_toEndOf="@+id/sourceImage"
app:layout_constraintTop_toTopOf="@+id/sourceImage" app:layout_constraintTop_toTopOf="@+id/sourceImage"
tools:text="Titre" /> tools:text="Titre" />
<TextView <TextView
android:id="@+id/sourceTitleAndDate" android:id="@+id/sourceTitleAndDate"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:gravity="start"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textSize="14sp"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
app:layout_constraintLeft_toLeftOf="@+id/title" android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/title"
app:layout_constraintTop_toBottomOf="@+id/title" app:layout_constraintTop_toBottomOf="@+id/title"
tools:text="Google Actualité Il y a 5h" /> tools:text="Google Actualité Il y a 5h" />
<RelativeLayout <LinearLayout
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sourceTitleAndDate"> app:layout_constraintTop_toBottomOf="@+id/sourceTitleAndDate">
<ImageButton <ImageButton
android:id="@+id/favButton" android:id="@+id/browserBtn"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:background="@android:color/transparent" android:background="@android:color/transparent"
android:contentDescription="@string/reader_action_open"
android:elevation="5dp" android:elevation="5dp"
android:padding="4dp" android:padding="4dp"
android:scaleType="centerCrop" android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_menu_heart_60dp" app:srcCompat="@drawable/ic_open_in_browser_black_24dp"
app:tint="@color/ic_menu_heart_color" /> app:tint="?android:attr/textColorPrimary" />
<ImageButton <ImageButton
android:id="@+id/shareBtn" android:id="@+id/shareBtn"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_centerVertical="true" android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_toLeftOf="@+id/favButton"
android:layout_toStartOf="@+id/favButton"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:background="@android:color/transparent" android:background="@android:color/transparent"
android:contentDescription="@string/share"
android:elevation="5dp" android:elevation="5dp"
android:padding="4dp" android:padding="4dp"
android:scaleType="centerCrop" android:scaleType="centerCrop"
@ -129,23 +112,21 @@
app:tint="?android:attr/textColorPrimary" /> app:tint="?android:attr/textColorPrimary" />
<ImageButton <ImageButton
android:id="@+id/browserBtn" android:id="@+id/favButton"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_centerVertical="true" android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_toLeftOf="@+id/shareBtn"
android:layout_toStartOf="@+id/shareBtn"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:background="@android:color/transparent" android:background="@android:color/transparent"
android:contentDescription="@string/add_to_favs_reader"
android:elevation="5dp" android:elevation="5dp"
android:padding="4dp" android:padding="4dp"
android:scaleType="centerCrop" android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_open_in_browser_black_24dp" app:srcCompat="@drawable/ic_menu_heart_60dp"
app:tint="?android:attr/textColorPrimary" /> app:tint="@color/ic_menu_heart_color" />
</RelativeLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -80,10 +79,11 @@
android:id="@+id/floatingActionButton2" android:id="@+id/floatingActionButton2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:clickable="true" android:clickable="true"
android:contentDescription="@string/menu_home_search"
android:focusable="true"
app:backgroundTint="@color/colorAccent" app:backgroundTint="@color/colorAccent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"

View File

@ -1,5 +1,4 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -22,10 +21,22 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="200dp" android:layout_height="200dp"
android:scaleType="centerCrop" android:scaleType="centerCrop"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent" />
/>
<TextView
android:id="@+id/titleView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:layout_marginRight="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<TextView <TextView
android:id="@+id/source" android:id="@+id/source"
@ -36,40 +47,23 @@
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:textColor="?android:textColorSecondary" android:textColor="?android:textColorSecondary"
android:textSize="12sp" android:textSize="12sp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/titleView" /> app:layout_constraintTop_toBottomOf="@+id/titleView" />
<TextView
android:id="@+id/titleView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
android:textStyle="bold"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<WebView <WebView
android:id="@+id/webcontent" android:id="@+id/webcontent"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="24dp"
android:layout_marginRight="16dp"
android:background="?attr/webviewBackground"
android:paddingBottom="48dp"
android:textColorLink="?attr/colorAccent" android:textColorLink="?attr/colorAccent"
android:visibility="gone" android:visibility="gone"
android:layout_marginLeft="16dp" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginRight="16dp" app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="24dp"
android:paddingBottom="48dp"
android:background="?attr/webviewBackground"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/source" app:layout_constraintTop_toBottomOf="@+id/source"
tools:visibility="visible" /> tools:visibility="visible" />
@ -80,10 +74,10 @@
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start|bottom|end"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="parent">
android:layout_gravity="end|bottom|right">
<com.github.rubensousa.floatingtoolbar.FloatingToolbar <com.github.rubensousa.floatingtoolbar.FloatingToolbar
android:id="@+id/floatingToolbar" android:id="@+id/floatingToolbar"
@ -96,12 +90,11 @@
android:id="@+id/fab" android:id="@+id/fab"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="end|bottom|right" android:layout_gravity="end|bottom"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginRight="16dp" android:layout_marginBottom="16dp"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin" android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:src="@drawable/ic_add_white_24dp" android:src="@drawable/ic_add_white_24dp"
app:backgroundTint="?attr/colorAccent" app:backgroundTint="?attr/colorAccent"
app:fabSize="mini" app:fabSize="mini"
@ -112,11 +105,11 @@
android:id="@+id/progressBar" android:id="@+id/progressBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:visibility="gone"
android:animateLayoutChanges="true"
android:alpha="0.8" android:alpha="0.8"
android:animateLayoutChanges="true"
android:background="@color/black" android:background="@color/black"
android:clickable="false"> android:clickable="false"
android:visibility="gone">
<ProgressBar <ProgressBar
style="?android:attr/progressBarStyleLarge" style="?android:attr/progressBarStyleLarge"

View File

@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.github.chrisbanes.photoview.PhotoView <com.github.chrisbanes.photoview.PhotoView
android:id="@+id/photoView" android:id="@+id/photoView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:background="@drawable/checkerboard" android:background="@drawable/checkerboard"
app:srcCompat="@android:drawable/screen_background_dark" /> app:srcCompat="@android:drawable/screen_background_dark" />
</RelativeLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -3,17 +3,16 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="88dp"> android:layout_height="wrap_content">
<ImageView <ImageView
android:id="@+id/itemImage" android:id="@+id/itemImage"
android:layout_width="46dp" android:layout_width="46dp"
android:layout_height="46dp" android:layout_height="46dp"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="21dp" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent" />
android:layout_marginLeft="8dp" />
<TextView <TextView
android:id="@+id/title" android:id="@+id/title"
@ -24,39 +23,30 @@
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:ellipsize="end" android:ellipsize="end"
android:fontFamily="sans-serif" android:fontFamily="sans-serif"
android:gravity="start"
android:maxLines="3" android:maxLines="3"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textAllCaps="false" android:textColor="?android:textColorPrimary"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="?android:textColorPrimary"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/itemImage" app:layout_constraintStart_toEndOf="@+id/itemImage"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="Titre" tools:text="Titre" />
android:layout_marginLeft="8dp"
android:layout_marginRight="16dp" />
<TextView <TextView
android:id="@+id/sourceTitleAndDate" android:id="@+id/sourceTitleAndDate"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="66dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:gravity="start" android:gravity="start"
android:maxLines="1" android:maxLines="1"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textSize="14sp"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/itemImage" app:layout_constraintStart_toEndOf="@+id/itemImage"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toBottomOf="@+id/itemImage"
tools:text="Google Actualité Il y a 5h" tools:text="Google Actualité Il y a 5h" />
android:layout_marginLeft="8dp"
android:layout_marginRight="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -12,9 +12,9 @@
style="@style/Widget.AppCompat.Button.Borderless" style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="48dp" android:layout_width="48dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/ic_remove_circle_outline_black_24dp" android:background="@drawable/ic_remove_circle_outline_black_24dp"
android:backgroundTint="?android:textColorSecondary" android:backgroundTint="?android:textColorSecondary"
android:contentDescription="@string/remove_source" android:contentDescription="@string/remove_source"
@ -29,48 +29,48 @@
android:id="@+id/itemImage" android:id="@+id/itemImage"
android:layout_width="36dp" android:layout_width="36dp"
android:layout_height="36dp" android:layout_height="36dp"
android:layout_marginBottom="8dp" android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:importantForAccessibility="no" android:importantForAccessibility="no"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" /> app:layout_constraintVertical_bias="0.0" />
<TextView <TextView
android:id="@+id/sourceTitle" android:id="@+id/sourceTitle"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="17dp" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:ellipsize="end" android:ellipsize="end"
android:gravity="start"
android:maxLines="1" android:maxLines="1"
android:textAlignment="textStart" android:textAlignment="viewStart"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
android:textSize="13sp" android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/errorText" app:layout_constraintBottom_toTopOf="@+id/errorText"
app:layout_constraintEnd_toStartOf="@+id/deleteBtn" app:layout_constraintEnd_toStartOf="@+id/deleteBtn"
app:layout_constraintStart_toEndOf="@+id/itemImage" app:layout_constraintStart_toEndOf="@+id/itemImage"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="source title" /> tools:text="Source title" />
<TextView <TextView
android:id="@+id/errorText" android:id="@+id/errorText"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp" android:layout_marginStart="10sp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="@color/red" android:textColor="@color/red"
android:textStyle="italic"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="@+id/deleteBtn"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/itemImage" app:layout_constraintTop_toBottomOf="@+id/itemImage"
tools:text="Test" tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
tools:visibility="visible" /> tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,16 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/open_action"
android:icon="@drawable/ic_open_in_browser_white_24dp"
android:title="@string/reader_action_open"
app:showAsAction="ifRoom" />
<item
android:id="@+id/share_action"
android:icon="@drawable/ic_share_white_24dp"
android:title="@string/reader_action_share"
app:showAsAction="ifRoom" />
</menu>

View File

@ -12,4 +12,5 @@
<color name="refresh_progress_2">@color/colorAccent</color> <color name="refresh_progress_2">@color/colorAccent</color>
<color name="refresh_progress_3">@color/pink</color> <color name="refresh_progress_3">@color/pink</color>
<color name="dark">#FF282828</color> <color name="dark">#FF282828</color>
<color name="transparent_dark_background">#33000000</color>
</resources> </resources>

View File

@ -26,4 +26,10 @@
<item name="android:textColorSecondary">@color/white</item> <item name="android:textColorSecondary">@color/white</item>
<item name="actionMenuTextColor">@color/white</item> <item name="actionMenuTextColor">@color/white</item>
</style> </style>
<style name="Theme.AppCompat.ImageActivity" parent="NoBar">
<item name="android:windowBackground">@color/transparent_dark_background</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
</style>
</resources> </resources>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto"
android:id="@+id/motionLayout">
<Transition
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end"
motion:duration="500"
motion:motionInterpolator="linear">
<OnSwipe
motion:touchAnchorId="@+id/scrollView"
motion:touchAnchorSide="top"
motion:onTouchUp="autoCompleteToStart" />
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@id/scrollView"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintTop_toBottomOf="@+id/appBarLayout"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent">
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/scrollView"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginBottom="0dp"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent">
</Constraint>
</ConstraintSet>
</MotionScene>

View File

@ -20,6 +20,8 @@ import org.junit.Test
private const val BASE_URL = "https://test.com/selfoss/" private const val BASE_URL = "https://test.com/selfoss/"
private const val USERNAME = "username"
private const val SPOUT = "spouts\\rss\\fulltextrss" private const val SPOUT = "spouts\\rss\\fulltextrss"
private const val IMAGE_URL = "b3aa8a664d08eb15d6ff1db2fa83e0d9.png" private const val IMAGE_URL = "b3aa8a664d08eb15d6ff1db2fa83e0d9.png"
@ -49,7 +51,7 @@ class RepositoryTest {
repository = Repository(api, appSettingsService, isConnectionAvailable, db) repository = Repository(api, appSettingsService, isConnectionAvailable, db)
runBlocking { runBlocking {
repository.updateApiVersion() repository.updateApiInformation()
} }
} }
@ -58,12 +60,13 @@ class RepositoryTest {
clearAllMocks() clearAllMocks()
every { appSettingsService.getApiVersion() } returns 4 every { appSettingsService.getApiVersion() } returns 4
every { appSettingsService.getBaseUrl() } returns BASE_URL every { appSettingsService.getBaseUrl() } returns BASE_URL
every { appSettingsService.getUserName() } returns USERNAME
every { appSettingsService.isItemCachingEnabled() } returns false every { appSettingsService.isItemCachingEnabled() } returns false
every { appSettingsService.isUpdateSourcesEnabled() } returns false every { appSettingsService.isUpdateSourcesEnabled() } returns false
coEvery { api.version() } returns StatusAndData( coEvery { api.apiInformation() } returns StatusAndData(
success = true, success = true,
data = SelfossModel.ApiVersion("2.19-ba1e8e3", "4.0.0") data = SelfossModel.ApiInformation("2.19-ba1e8e3", "4.0.0", SelfossModel.ApiConfiguration(false, true))
) )
coEvery { api.stats() } returns StatusAndData( coEvery { api.stats() } returns StatusAndData(
success = true, success = true,
@ -81,7 +84,7 @@ class RepositoryTest {
fun instantiate_repository() { fun instantiate_repository() {
initializeRepository() initializeRepository()
coVerify(exactly = 1) { api.version() } coVerify(exactly = 1) { api.apiInformation() }
} }
@Test @Test
@ -90,7 +93,7 @@ class RepositoryTest {
initializeRepository(MutableStateFlow(false)) initializeRepository(MutableStateFlow(false))
coVerify(exactly = 0) { api.version() } coVerify(exactly = 0) { api.apiInformation() }
coVerify(exactly = 0) { api.stats() } coVerify(exactly = 0) { api.stats() }
} }
@ -110,10 +113,70 @@ class RepositoryTest {
verify(exactly = 1) { appSettingsService.updateApiVersion(4) } verify(exactly = 1) { appSettingsService.updateApiVersion(4) }
} }
@Test
fun get_public_access() {
every { appSettingsService.updatePublicAccess(any()) } returns Unit
coEvery { api.apiInformation() } returns StatusAndData(
success = true,
data = SelfossModel.ApiInformation("2.19-ba1e8e3", "4.0.0", SelfossModel.ApiConfiguration(true, true))
)
every { appSettingsService.getUserName() } returns ""
initializeRepository()
coVerify(exactly = 1) { api.apiInformation() }
coVerify(exactly = 1) { appSettingsService.updatePublicAccess(true) }
}
@Test
fun get_public_access_username_not_empty() {
every { appSettingsService.updatePublicAccess(any()) } returns Unit
coEvery { api.apiInformation() } returns StatusAndData(
success = true,
data = SelfossModel.ApiInformation("2.19-ba1e8e3", "4.0.0", SelfossModel.ApiConfiguration(true, true))
)
every { appSettingsService.getUserName() } returns "username"
initializeRepository()
coVerify(exactly = 1) { api.apiInformation() }
coVerify(exactly = 0) { appSettingsService.updatePublicAccess(true) }
}
@Test
fun get_public_access_no_auth() {
every { appSettingsService.updatePublicAccess(any()) } returns Unit
coEvery { api.apiInformation() } returns StatusAndData(
success = true,
data = SelfossModel.ApiInformation("2.19-ba1e8e3", "4.0.0", SelfossModel.ApiConfiguration(true, false))
)
every { appSettingsService.getUserName() } returns ""
initializeRepository()
coVerify(exactly = 1) { api.apiInformation() }
coVerify(exactly = 0) { appSettingsService.updatePublicAccess(true) }
}
@Test
fun get_public_access_disabled() {
every { appSettingsService.updatePublicAccess(any()) } returns Unit
coEvery { api.apiInformation() } returns StatusAndData(
success = true,
data = SelfossModel.ApiInformation("2.19-ba1e8e3", "4.0.0", SelfossModel.ApiConfiguration(false, true))
)
every { appSettingsService.getUserName() } returns ""
initializeRepository()
coVerify(exactly = 1) { api.apiInformation() }
coVerify(exactly = 0) { appSettingsService.updatePublicAccess(true) }
}
@Test @Test
fun get_api_1_date_with_api_4_version_stored() { fun get_api_1_date_with_api_4_version_stored() {
every { appSettingsService.getApiVersion() } returns 4 every { appSettingsService.getApiVersion() } returns 4
coEvery { api.version() } returns StatusAndData(success = false, null) coEvery { api.apiInformation() } returns StatusAndData(success = false, null)
val itemParameters = FakeItemParameters() val itemParameters = FakeItemParameters()
itemParameters.datetime = "2021-04-23 11:45:32" itemParameters.datetime = "2021-04-23 11:45:32"
coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns coEvery { api.getItems(any(), any(), any(), any(), any(), any(), any()) } returns

View File

@ -9,7 +9,6 @@ import org.kodein.di.instance
import org.kodein.di.singleton import org.kodein.di.singleton
val networkModule by DI.Module { val networkModule by DI.Module {
bind<AppSettingsService>() with singleton { AppSettingsService() }
bind<SelfossApi>() with singleton { SelfossApi(instance()) } bind<SelfossApi>() with singleton { SelfossApi(instance()) }
bind<MercuryApi>() with singleton { MercuryApi() } bind<MercuryApi>() with singleton { MercuryApi() }
} }

View File

@ -35,17 +35,32 @@ class SelfossModel {
) )
@Serializable @Serializable
data class ApiVersion( data class ApiInformation(
val version: String?, val version: String?,
val apiversion: String? val apiversion: String?,
val configuration: ApiConfiguration?
) { ) {
fun getApiMajorVersion() : Int { fun getApiMajorVersion(): Int {
var versionNumber = 0 var versionNumber = 0
if (apiversion != null) { if (apiversion != null) {
versionNumber = apiversion.substringBefore(".").toInt() versionNumber = apiversion.substringBefore(".").toInt()
} }
return versionNumber return versionNumber
} }
fun getApiConfiguration() = configuration ?: ApiConfiguration(null, null)
}
@Serializable
data class ApiConfiguration(
@Serializable(with = BooleanSerializer::class)
val publicMode: Boolean?,
@Serializable(with = BooleanSerializer::class)
val authEnabled: Boolean?
) {
fun isAuthEnabled() = authEnabled ?: true
fun isPublicModeEnabled() = publicMode ?: false
} }
@Serializable @Serializable

View File

@ -439,13 +439,23 @@ class Repository(
api.refreshLoginInformation() api.refreshLoginInformation()
} }
suspend fun updateApiVersion() { suspend fun updateApiInformation() {
val apiMajorVersion = appSettingsService.getApiVersion() val apiMajorVersion = appSettingsService.getApiVersion()
if (isNetworkAvailable()) { if (isNetworkAvailable()) {
val fetchedVersion = api.version() val fetchedInformation = api.apiInformation()
if (fetchedVersion.success && fetchedVersion.data != null && fetchedVersion.data.getApiMajorVersion() != apiMajorVersion) { if (fetchedInformation.success && fetchedInformation.data != null) {
appSettingsService.updateApiVersion(fetchedVersion.data.getApiMajorVersion()) if (fetchedInformation.data.getApiMajorVersion() != apiMajorVersion) {
appSettingsService.updateApiVersion(fetchedInformation.data.getApiMajorVersion())
}
// Check if we're accessing the instance in public mode
// This happens when auth and public mode are enabled but
// no credentials are provided to login
if (appSettingsService.getUserName().isEmpty()
&& fetchedInformation.data.getApiConfiguration().isAuthEnabled()
&& fetchedInformation.data.getApiConfiguration().isPublicModeEnabled()) {
appSettingsService.updatePublicAccess(true)
}
} }
} }
} }

View File

@ -191,7 +191,7 @@ class SelfossApi(private val appSettingsService: AppSettingsService) {
} }
}) })
suspend fun version(): StatusAndData<SelfossModel.ApiVersion> = suspend fun apiInformation(): StatusAndData<SelfossModel.ApiInformation> =
bodyOrFailure(client.tryToGet(url("/api/about"))) bodyOrFailure(client.tryToGet(url("/api/about")))
suspend fun markAsRead(id: String): SuccessResponse = suspend fun markAsRead(id: String): SuccessResponse =

View File

@ -0,0 +1,70 @@
package bou.amine.apps.readerforselfossv2.service
import com.russhwolf.settings.Settings
// This will be used in ACRA process. For now, it does nothing.
// This is to fix ACRA not sending reports anymore.
// See https://www.acra.ch/docs/Troubleshooting-Guide#applicationoncreate
class ACRASettings : Settings {
override val keys: Set<String> = emptySet()
override val size: Int = 0
override fun clear() {
// Nothing
}
override fun getBoolean(key: String, defaultValue: Boolean): Boolean = false
override fun getBooleanOrNull(key: String): Boolean? = null
override fun getDouble(key: String, defaultValue: Double): Double = 0.0
override fun getDoubleOrNull(key: String): Double? = null
override fun getFloat(key: String, defaultValue: Float): Float = 0.0F
override fun getFloatOrNull(key: String): Float? = null
override fun getInt(key: String, defaultValue: Int): Int = 0
override fun getIntOrNull(key: String): Int? = null
override fun getLong(key: String, defaultValue: Long): Long = 0
override fun getLongOrNull(key: String): Long? = null
override fun getString(key: String, defaultValue: String): String = "0"
override fun getStringOrNull(key: String): String? = null
override fun hasKey(key: String): Boolean = false
override fun putBoolean(key: String, value: Boolean) {
// Nothing
}
override fun putDouble(key: String, value: Double) {
// Nothing
}
override fun putFloat(key: String, value: Float) {
// Nothing
}
override fun putInt(key: String, value: Int) {
// Nothing
}
override fun putLong(key: String, value: Long) {
// Nothing
}
override fun putString(key: String, value: String) {
// Nothing
}
override fun remove(key: String) {
// Nothing
}
}

View File

@ -2,11 +2,12 @@ package bou.amine.apps.readerforselfossv2.service
import com.russhwolf.settings.Settings import com.russhwolf.settings.Settings
class AppSettingsService { class AppSettingsService(acraSenderServiceProcess: Boolean = false) {
val settings: Settings = Settings() val settings: Settings = if (acraSenderServiceProcess) { ACRASettings() } else { Settings() }
// Api related // Api related
private var _apiVersion: Int = -1 private var _apiVersion: Int = -1
private var _publicAccess: Boolean? = null
private var _baseUrl: String = "" private var _baseUrl: String = ""
private var _userName: String = "" private var _userName: String = ""
private var _password: String = "" private var _password: String = ""
@ -48,10 +49,32 @@ class AppSettingsService {
return _apiVersion return _apiVersion
} }
fun updateApiVersion(apiMajorVersion: Int) {
settings.putInt(API_VERSION_MAJOR, apiMajorVersion)
refreshApiVersion()
}
private fun refreshApiVersion() { private fun refreshApiVersion() {
_apiVersion = settings.getInt(API_VERSION_MAJOR, -1) _apiVersion = settings.getInt(API_VERSION_MAJOR, -1)
} }
fun getPublicAccess(): Boolean {
if (_publicAccess == null) {
refreshPublicAccess()
}
return _publicAccess!!
}
fun updatePublicAccess(publicAccess: Boolean) {
settings.putBoolean(API_PUBLIC_ACCESS, publicAccess)
refreshPublicAccess()
}
private fun refreshPublicAccess() {
_publicAccess = settings.getBoolean(API_PUBLIC_ACCESS, false)
}
fun getBaseUrl(): String { fun getBaseUrl(): String {
if (_baseUrl.isEmpty()) { if (_baseUrl.isEmpty()) {
refreshBaseUrl() refreshBaseUrl()
@ -333,6 +356,7 @@ class AppSettingsService {
refreshUsername() refreshUsername()
refreshBaseUrl() refreshBaseUrl()
refreshApiVersion() refreshApiVersion()
refreshPublicAccess()
} }
fun refreshUserSettings() { fun refreshUserSettings() {
@ -376,11 +400,6 @@ class AppSettingsService {
refreshApiSettings() refreshApiSettings()
} }
fun updateApiVersion(apiMajorVersion: Int) {
settings.putInt(API_VERSION_MAJOR, apiMajorVersion)
refreshApiVersion()
}
fun clearAll() { fun clearAll() {
settings.clear() settings.clear()
refreshApiSettings() refreshApiSettings()
@ -409,6 +428,8 @@ class AppSettingsService {
const val API_VERSION_MAJOR = "apiVersionMajor" const val API_VERSION_MAJOR = "apiVersionMajor"
const val API_PUBLIC_ACCESS = "apiPublicAccess"
const val API_ITEMS_NUMBER = "prefer_api_items_number" const val API_ITEMS_NUMBER = "prefer_api_items_number"
const val API_TIMEOUT = "api_timeout" const val API_TIMEOUT = "api_timeout"