Compare commits

...

9 Commits

Author SHA1 Message Date
f0b073e74d Upgrade dependencies 2022-01-16 13:10:22 +01:00
ca5186d20a Clear settings on logout (#395) 2022-01-08 16:26:34 +01:00
78d5744139 Fix button readall not working as soon as the app was started but only after switching category. (#393) 2022-01-07 20:46:06 +01:00
b2609554e6 Fix dark dialog background (#392) 2022-01-06 19:50:19 +01:00
5db312bbb8 Simplify ArticleFragment logic (#388)
* Send a single article to ArticleFragment

* Allow using the internal browser
2021-12-14 20:09:50 +01:00
7592ab512b Migrate to Viewpager2 (#387)
* Migrate ReaderActivity to ViewPager2

* Use tint on icons in place of filters

* Prevent crash when opening the first article

* Add the correct background color to the article reader

* Use consistent colors in the article reader

* Migrate ImageActivity to ViewPager2
2021-12-13 20:29:38 +01:00
000b346529 Fix crash when editing sources (#385) 2021-12-09 20:17:45 +01:00
1bb975c584 Substitute some deprecated functions (#386)
* Deprecated color filter

* Various deprecated functions
2021-12-09 20:17:16 +01:00
69aaa323e2 Theme (#375)
* Fix sources colors

* Fix issues with sources

* Simplify card view theme

* Simplify list item theming

* Simplify article viewer theming

* Fix issues with the color selection.

* Correct the color of sources text in article reader
2021-11-29 20:26:18 +01:00
29 changed files with 211 additions and 318 deletions

View File

@ -104,18 +104,18 @@ dependencies {
// Espresso-intents for validation and stubbing of Intents
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0-alpha02'
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// Android Support
implementation "androidx.appcompat:appcompat:1.4.0-beta01"
implementation 'com.google.android.material:material:1.5.0-alpha04'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.recyclerview:recyclerview:1.3.0-alpha01'
implementation "androidx.legacy:legacy-support-v4:$android_version"
implementation 'androidx.vectordrawable:vectordrawable:1.2.0-alpha02'
implementation "androidx.browser:browser:1.3.0"
implementation 'androidx.browser:browser:1.4.0'
implementation "androidx.cardview:cardview:$android_version"
implementation "androidx.annotation:annotation:1.2.0"
implementation 'androidx.work:work-runtime-ktx:2.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation 'androidx.annotation:annotation:1.3.0'
implementation 'androidx.work:work-runtime-ktx:2.7.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'org.jsoup:jsoup:1.14.3'
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")
@ -129,11 +129,11 @@ dependencies {
implementation "com.mikepenz:aboutlibraries-definitions:8.9.4"
// Async
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
// Retrofit + http logging + okhttp
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.3'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.burgstaller:okhttp-digest:2.5'
@ -146,7 +146,7 @@ dependencies {
implementation 'com.github.bumptech.glide:okhttp3-integration:4.1.1'
// Drawer
implementation 'com.mikepenz:materialdrawer:8.4.4'
implementation 'com.mikepenz:materialdrawer:8.4.5'
// Themes
implementation 'com.52inc:scoops:1.0.0'
@ -155,14 +155,15 @@ dependencies {
// Pager
implementation 'me.relex:circleindicator:2.1.6'
implementation "androidx.viewpager2:viewpager2:1.1.0-beta01"
//PhotoView
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
implementation 'androidx.core:core-ktx:1.7.0-rc01'
implementation 'androidx.core:core-ktx:1.7.0'
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.0-rc01"
implementation "androidx.lifecycle:lifecycle-common-java8:2.4.0-rc01"
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.4.0'
implementation "androidx.room:room-ktx:2.4.0-beta01"
kapt "androidx.room:room-compiler:2.4.0-beta01"

View File

@ -52,19 +52,19 @@ class AddSourceActivity : AppCompatActivity() {
scoop.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
val drawable = binding.nameInput.background
drawable.setColorFilter(appColors.colorAccent, PorterDuff.Mode.SRC_ATOP)
drawable.setTint(appColors.colorAccent)
// TODO: clean
binding.nameInput.background = drawable
val drawable1 = binding.sourceUri.background
drawable1.setColorFilter(appColors.colorAccent, PorterDuff.Mode.SRC_ATOP)
drawable1.setTint(appColors.colorAccent)
binding.sourceUri.background = drawable1
val drawable2 = binding.tags.background
drawable2.setColorFilter(appColors.colorAccent, PorterDuff.Mode.SRC_ATOP)
drawable2.setTint(appColors.colorAccent)
binding.tags.background = drawable2

View File

@ -100,7 +100,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private var displayAllCount = false
private var fullHeightCards: Boolean = false
private var itemsNumber: Int = 200
private var elementsShown: Int = 0
private var elementsShown: Int = 1
private var maybeTagFilter: Tag? = null
private var maybeSourceFilter: Source? = null
private var maybeSearchFilter: String? = null

View File

@ -3,8 +3,9 @@ package apps.amine.bou.readerforselfoss
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import apps.amine.bou.readerforselfoss.databinding.ActivityImageBinding
import apps.amine.bou.readerforselfoss.fragments.ImageFragment
@ -28,8 +29,8 @@ class ImageActivity : AppCompatActivity() {
allImages = intent.getStringArrayListExtra("allImages") as ArrayList<String>
position = intent.getIntExtra("position", 0)
binding.pager.adapter = ScreenSlidePagerAdapter(supportFragmentManager)
binding.pager.currentItem = position
binding.pager.adapter = ScreenSlidePagerAdapter(this)
binding.pager.setCurrentItem(position, false)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -43,14 +44,10 @@ class ImageActivity : AppCompatActivity() {
return super.onOptionsItemSelected(item)
}
private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm, FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
override fun getCount(): Int {
return allImages.size
}
override fun getItemCount(): Int = allImages.size
override fun getItem(position: Int): ImageFragment {
return ImageFragment.newInstance(allImages[position])
}
override fun createFragment(position: Int): Fragment = ImageFragment.newInstance(allImages[position])
}
}

View File

@ -14,11 +14,11 @@ import android.view.MenuItem
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.TextView
import androidx.preference.PreferenceManager
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.databinding.ActivityLoginBinding
import apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible
import com.mikepenz.aboutlibraries.LibsBuilder
@ -52,7 +52,7 @@ class LoginActivity : AppCompatActivity() {
handleBaseUrlFail()
settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
settings = PreferenceManager.getDefaultSharedPreferences(applicationContext)
userIdentifier = settings.getString("unique_id", "")!!
editor = settings.edit()

View File

@ -61,14 +61,14 @@ class MyApp : MultiDexApplication() {
private fun initDrawerImageLoader() {
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
Glide.with(imageView?.context)
Glide.with(imageView.context)
.loadMaybeBasicAuth(config, uri.toString())
.apply(RequestOptions.fitCenterTransform().placeholder(placeholder))
.into(imageView)
}
override fun cancel(imageView: ImageView) {
Glide.with(imageView?.context).clear(imageView)
Glide.with(imageView.context).clear(imageView)
}
override fun placeholder(ctx: Context, tag: String?): Drawable {

View File

@ -3,21 +3,16 @@ package apps.amine.bou.readerforselfoss
import android.content.Context
import android.content.SharedPreferences
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import androidx.preference.PreferenceManager
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.core.content.ContextCompat
import androidx.viewpager.widget.ViewPager
import androidx.appcompat.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.room.Room
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.databinding.ActivityReaderBinding
@ -28,18 +23,17 @@ import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_2_3
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_3_4
import apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.themes.Toppings
import apps.amine.bou.readerforselfoss.transformers.DepthPageTransformer
import apps.amine.bou.readerforselfoss.utils.Config
import apps.amine.bou.readerforselfoss.utils.SharedItems
import apps.amine.bou.readerforselfoss.utils.toggleStar
import com.ftinc.scoop.Scoop
import me.relex.circleindicator.CircleIndicator
class ReaderActivity : AppCompatActivity() {
private var markOnScroll: Boolean = false
private var currentItem: Int = 0
private lateinit var userIdentifier: String
private lateinit var appColors: AppColors
private lateinit var api: SelfossApi
@ -50,14 +44,14 @@ class ReaderActivity : AppCompatActivity() {
private lateinit var binding: ActivityReaderBinding
private var activeAlignment: Int = 1
val JUSTIFY = 1
val ALIGN_LEFT = 2
private val JUSTIFY = 1
private val ALIGN_LEFT = 2
private fun showMenuItem(willAddToFavorite: Boolean) {
if (willAddToFavorite) {
toolbarMenu.findItem(R.id.star).icon.colorFilter = PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP)
toolbarMenu.findItem(R.id.star).icon.setTint(Color.WHITE)
} else {
toolbarMenu.findItem(R.id.star).icon.colorFilter = PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP)
toolbarMenu.findItem(R.id.star).icon.setTint(Color.RED)
}
}
@ -73,6 +67,7 @@ class ReaderActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
appColors = AppColors(this)
binding = ActivityReaderBinding.inflate(layoutInflater)
val view = binding.root
@ -116,33 +111,14 @@ class ReaderActivity : AppCompatActivity() {
readItem(allItems[currentItem])
binding.pager.adapter =
ScreenSlidePagerAdapter(supportFragmentManager, AppColors(this@ReaderActivity))
binding.pager.currentItem = currentItem
binding.pager.adapter = ScreenSlidePagerAdapter(this)
binding.pager.setCurrentItem(currentItem, false)
}
override fun onResume() {
super.onResume()
notifyAdapter()
binding.pager.setPageTransformer(true, DepthPageTransformer())
(binding.indicator as CircleIndicator).setViewPager(binding.pager)
binding.pager.addOnPageChangeListener(
object : ViewPager.SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) {
if (allItems[position].starred) {
canRemoveFromFavorite()
} else {
canFavorite()
}
readItem(allItems[position])
}
}
)
binding.indicator.setViewPager(binding.pager)
}
private fun readItem(item: Item) {
@ -151,46 +127,22 @@ class ReaderActivity : AppCompatActivity() {
}
}
private fun notifyAdapter() {
(binding.pager.adapter as ScreenSlidePagerAdapter).notifyDataSetChanged()
}
override fun onPause() {
super.onPause()
if (markOnScroll) {
binding.pager.clearOnPageChangeListeners()
}
}
override fun onSaveInstanceState(oldInstanceState: Bundle) {
super.onSaveInstanceState(oldInstanceState)
oldInstanceState.clear()
}
private inner class ScreenSlidePagerAdapter(fm: FragmentManager, val appColors: AppColors) :
FragmentStatePagerAdapter(fm) {
private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) :
FragmentStateAdapter(fa) {
override fun getCount(): Int {
return allItems.size
}
override fun getItem(position: Int): ArticleFragment {
return ArticleFragment.newInstance(position, allItems)
}
override fun getItemCount(): Int = allItems.size
override fun startUpdate(container: ViewGroup) {
super.startUpdate(container)
override fun createFragment(position: Int): Fragment = ArticleFragment.newInstance(allItems[position])
container.background = ColorDrawable(
ContextCompat.getColor(
this@ReaderActivity,
appColors.colorBackground
)
)
}
}
fun alignmentMenu(showJustify: Boolean) {
private fun alignmentMenu(showJustify: Boolean) {
toolbarMenu.findItem(R.id.align_left).isVisible = !showJustify
toolbarMenu.findItem(R.id.align_justify).isVisible = showJustify
}
@ -200,7 +152,7 @@ class ReaderActivity : AppCompatActivity() {
inflater.inflate(R.menu.reader_menu, menu)
toolbarMenu = menu
if (!allItems.isEmpty() && allItems[currentItem].starred) {
if (allItems.isNotEmpty() && allItems[currentItem].starred) {
canRemoveFromFavorite()
} else {
canFavorite()
@ -211,6 +163,22 @@ class ReaderActivity : AppCompatActivity() {
alignmentMenu(true)
}
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
}
@ -218,13 +186,11 @@ class ReaderActivity : AppCompatActivity() {
fun afterSave() {
allItems[binding.pager.currentItem] =
allItems[binding.pager.currentItem].toggleStar()
notifyAdapter()
canRemoveFromFavorite()
}
fun afterUnsave() {
allItems[binding.pager.currentItem] = allItems[binding.pager.currentItem].toggleStar()
notifyAdapter()
canFavorite()
}

View File

@ -28,17 +28,17 @@ class SourcesActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
appColors = AppColors(this@SourcesActivity)
super.onCreate(savedInstanceState)
binding = ActivitySourcesBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
val scoop = Scoop.getInstance()
scoop.bind(this, Toppings.PRIMARY.value, binding.toolbar)
scoop.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
super.onCreate(savedInstanceState)
setContentView(view)
setSupportActionBar(binding.toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)

View File

@ -7,7 +7,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView.ScaleType
import androidx.core.content.ContextCompat
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
@ -61,10 +60,6 @@ class ItemCardAdapter(
binding.favButton.isSelected = itm.starred
binding.title.text = itm.getTitleDecoded()
binding.title.setTextColor(ContextCompat.getColor(
c,
appColors.textColor
))
binding.title.setOnTouchListener(LinkOnTouchListener())
@ -72,11 +67,6 @@ class ItemCardAdapter(
binding.sourceTitleAndDate.text = itm.sourceAndDateText()
binding.sourceTitleAndDate.setTextColor(ContextCompat.getColor(
c,
appColors.textColor
))
if (!fullHeightCards) {
binding.itemImage.maxHeight = imageMaxHeight
binding.itemImage.scaleType = ScaleType.CENTER_CROP
@ -112,7 +102,6 @@ class ItemCardAdapter(
inner class ViewHolder(val binding: CardItemBinding) : RecyclerView.ViewHolder(binding.root) {
init {
binding.root.setCardBackgroundColor(appColors.cardBackgroundColor)
handleClickListeners()
handleCustomTabActions()
}

View File

@ -5,7 +5,6 @@ import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import apps.amine.bou.readerforselfoss.api.selfoss.Item
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.databinding.ListItemBinding
@ -49,25 +48,14 @@ class ItemListAdapter(
with(holder) {
val itm = items[position]
binding.title.text = itm.getTitleDecoded()
binding.title.setTextColor(ContextCompat.getColor(
c,
appColors.textColor
))
binding.title.setOnTouchListener(LinkOnTouchListener())
binding.title.setLinkTextColor(appColors.colorAccent)
binding.sourceTitleAndDate.text = itm.sourceAndDateText()
binding.sourceTitleAndDate.setTextColor(ContextCompat.getColor(
c,
appColors.textColor
))
if (itm.getThumbnail(c).isEmpty()) {
if (itm.getIcon(c).isEmpty()) {

View File

@ -14,6 +14,8 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
import com.google.gson.annotations.SerializedName
import java.util.*
import kotlin.collections.ArrayList
private fun constructUrl(config: Config?, path: String, file: String?): String {
return if (file.isEmptyOrNullOrNullString()) {
@ -155,14 +157,14 @@ data class Item(
}
fun getImages() : ArrayList<String> {
var allImages = ArrayList<String>()
val allImages = ArrayList<String>()
for ( image in Jsoup.parse(content).getElementsByTag("img")) {
val url = image.attr("src")
if (url.toLowerCase().contains(".jpg") ||
url.toLowerCase().contains(".jpeg") ||
url.toLowerCase().contains(".png") ||
url.toLowerCase().contains(".webp"))
if (url.lowercase(Locale.US).contains(".jpg") ||
url.lowercase(Locale.US).contains(".jpeg") ||
url.lowercase(Locale.US).contains(".png") ||
url.lowercase(Locale.US).contains(".webp"))
{
allImages.add(url)
}

View File

@ -14,12 +14,11 @@ import androidx.preference.PreferenceManager
import android.view.*
import android.webkit.*
import android.widget.Toast
import androidx.browser.customtabs.CustomTabsIntent
import com.google.android.material.floatingactionbutton.FloatingActionButton
import androidx.fragment.app.Fragment
import androidx.core.content.ContextCompat
import androidx.core.widget.NestedScrollView
import androidx.appcompat.app.AlertDialog
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.content.res.ResourcesCompat
import androidx.room.Room
import apps.amine.bou.readerforselfoss.ImageActivity
@ -48,14 +47,14 @@ import retrofit2.Callback
import retrofit2.Response
import java.net.MalformedURLException
import java.net.URL
import java.util.*
import java.util.concurrent.ExecutionException
import kotlin.collections.ArrayList
class ArticleFragment : Fragment() {
private lateinit var pageNumber: Number
private var fontSize: Int = 16
private lateinit var allItems: ArrayList<Item>
private var mCustomTabActivityHelper: CustomTabActivityHelper? = null;
private lateinit var item: Item
private var mCustomTabActivityHelper: CustomTabActivityHelper? = null
private lateinit var url: String
private lateinit var contentText: String
private lateinit var contentSource: String
@ -91,8 +90,7 @@ class ArticleFragment : Fragment() {
super.onCreate(savedInstanceState)
pageNumber = requireArguments().getInt(ARG_POSITION)
allItems = requireArguments().getParcelableArrayList<Item>(ARG_ITEMS) as ArrayList<Item>
item = requireArguments().getParcelable(ARG_ITEMS)!!
db = Room.databaseBuilder(
requireContext(),
@ -104,16 +102,16 @@ class ArticleFragment : Fragment() {
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
): View {
try {
_binding = FragmentArticleBinding.inflate(inflater, container, false)
url = allItems[pageNumber.toInt()].getLinkDecoded()
contentText = allItems[pageNumber.toInt()].content
contentTitle = allItems[pageNumber.toInt()].getTitleDecoded()
contentImage = allItems[pageNumber.toInt()].getThumbnail(requireActivity())
contentSource = allItems[pageNumber.toInt()].sourceAndDateText()
allImages = allItems[pageNumber.toInt()].getImages()
url = item.getLinkDecoded()
contentText = item.content
contentTitle = item.getTitleDecoded()
contentImage = item.getThumbnail(requireActivity())
contentSource = item.sourceAndDateText()
allImages = item.getImages()
prefs = PreferenceManager.getDefaultSharedPreferences(activity)
editor = prefs.edit()
@ -163,26 +161,18 @@ class ArticleFragment : Fragment() {
object : FloatingToolbar.ItemClickListener {
override fun onItemClick(item: MenuItem) {
when (item.itemId) {
R.id.more_action -> getContentFromMercury(customTabsIntent, prefs)
R.id.more_action -> getContentFromMercury(customTabsIntent)
R.id.share_action -> requireActivity().shareLink(url, contentTitle)
R.id.open_action -> requireActivity().openItemUrl(
allItems,
pageNumber.toInt(),
url,
customTabsIntent,
false,
false,
requireActivity()
)
R.id.open_action -> requireActivity().openInBrowserAsNewTask(this@ArticleFragment.item)
R.id.unread_action -> if (context != null) {
if (allItems[pageNumber.toInt()].unread) {
if (this@ArticleFragment.item.unread) {
SharedItems.readItem(
context!!,
api,
db,
allItems[pageNumber.toInt()]
this@ArticleFragment.item
)
allItems[pageNumber.toInt()].unread = false
this@ArticleFragment.item.unread = false
Toast.makeText(
context,
R.string.marked_as_read,
@ -193,9 +183,9 @@ class ArticleFragment : Fragment() {
context!!,
api,
db,
allItems[pageNumber.toInt()]
this@ArticleFragment.item
)
allItems[pageNumber.toInt()].unread = true
this@ArticleFragment.item.unread = true
Toast.makeText(
context,
R.string.marked_as_unread,
@ -223,7 +213,7 @@ class ArticleFragment : Fragment() {
}
if (contentText.isEmptyOrNullOrNullString()) {
getContentFromMercury(customTabsIntent, prefs)
getContentFromMercury(customTabsIntent)
} else {
binding.titleView.text = contentTitle
if (typeface != null) {
@ -265,11 +255,11 @@ class ArticleFragment : Fragment() {
.setMessage(requireContext().getString(R.string.webview_dialog_issue_message))
.setTitle(requireContext().getString(R.string.webview_dialog_issue_title))
.setPositiveButton(android.R.string.ok
) { dialog, which ->
) { _, _ ->
val sharedPref = PreferenceManager.getDefaultSharedPreferences(requireContext())
val editor = sharedPref.edit()
editor.putBoolean("prefer_article_viewer", false)
editor.commit()
editor.apply()
requireActivity().finish()
}
.create()
@ -292,10 +282,7 @@ class ArticleFragment : Fragment() {
}
}
private fun getContentFromMercury(
customTabsIntent: CustomTabsIntent,
prefs: SharedPreferences
) {
private fun getContentFromMercury(customTabsIntent: CustomTabsIntent) {
if ((context != null && requireContext().isNetworkAccessible(null)) || context == null) {
binding.progressBar.visibility = View.VISIBLE
val parser = MercuryApi()
@ -390,42 +377,12 @@ class ArticleFragment : Fragment() {
binding.webcontent.settings.standardFontFamily = a.getString(0)
binding.webcontent.visibility = View.VISIBLE
val (textColor, backgroundColor) = if (appColors.isDarkTheme) {
if (context != null) {
binding.webcontent.setBackgroundColor(
ContextCompat.getColor(
requireContext(),
R.color.dark_webview
)
)
Pair(ContextCompat.getColor(requireContext(), R.color.dark_webview_text), ContextCompat.getColor(requireContext(), R.color.dark_webview))
} else {
Pair(null, null)
}
} else {
if (context != null) {
binding.webcontent.setBackgroundColor(
ContextCompat.getColor(
requireContext(),
R.color.light_webview
)
)
Pair(ContextCompat.getColor(requireContext(), R.color.light_webview_text), ContextCompat.getColor(requireContext(), R.color.light_webview))
} else {
Pair(null, null)
}
}
val stringTextColor: String = if (textColor != null) {
String.format("#%06X", 0xFFFFFF and textColor)
// TODO: Set the color strings programmatically
val (stringTextColor, stringBackgroundColor) = if (appColors.isDarkTheme) {
Pair("#FFFFFF", "#303030")
} else {
"#000000"
}
val stringBackgroundColor = if (backgroundColor != null) {
String.format("#%06X", 0xFFFFFF and backgroundColor)
} else {
"#FFFFFF"
Pair("#212121", "#FAFAFA")
}
binding.webcontent.settings.useWideViewPort = true
@ -442,19 +399,19 @@ class ArticleFragment : Fragment() {
override fun shouldInterceptRequest(view: WebView?, url: String): WebResourceResponse? {
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
if (url.toLowerCase().contains(".jpg") || url.toLowerCase().contains(".jpeg")) {
if (url.lowercase(Locale.US).contains(".jpg") || url.lowercase(Locale.US).contains(".jpeg")) {
try {
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.JPEG))
}catch ( e : ExecutionException) {}
}
else if (url.toLowerCase().contains(".png")) {
else if (url.lowercase(Locale.US).contains(".png")) {
try {
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.PNG))
}catch ( e : ExecutionException) {}
}
else if (url.toLowerCase().contains(".webp")) {
else if (url.lowercase(Locale.US).contains(".webp")) {
try {
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.WEBP))
@ -556,29 +513,22 @@ class ArticleFragment : Fragment() {
private fun openInBrowserAfterFailing(customTabsIntent: CustomTabsIntent) {
binding.progressBar.visibility = View.GONE
requireActivity().openItemUrl(
allItems,
pageNumber.toInt(),
url,
customTabsIntent,
true,
false,
requireActivity()
requireActivity().openItemUrlInternalBrowser(
url,
customTabsIntent,
requireActivity()
)
}
companion object {
private const val ARG_POSITION = "position"
private const val ARG_ITEMS = "items"
fun newInstance(
position: Int,
allItems: ArrayList<Item>
item: Item
): ArticleFragment {
val fragment = ArticleFragment()
val args = Bundle()
args.putInt(ARG_POSITION, position)
args.putParcelableArrayList(ARG_ITEMS, allItems)
args.putParcelable(ARG_ITEMS, item)
fragment.arguments = args
return fragment
}

View File

@ -13,7 +13,10 @@ import androidx.core.widget.addTextChangedListener
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import apps.amine.bou.readerforselfoss.R
import apps.amine.bou.readerforselfoss.databinding.ActivitySettingsBinding
import apps.amine.bou.readerforselfoss.themes.Toppings
import apps.amine.bou.readerforselfoss.utils.Config
import com.ftinc.scoop.Scoop
import java.lang.NumberFormatException
private const val TITLE_TAG = "settingsActivityTitle"
@ -26,7 +29,13 @@ class SettingsActivity : AppCompatActivity(),
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", false)) {
setTheme(R.style.NoBarDark)
}
setContentView(R.layout.activity_settings)
val binding = ActivitySettingsBinding.inflate(layoutInflater)
val scoop = Scoop.getInstance()
scoop.bind(this, Toppings.PRIMARY.value, binding.toolbar)
scoop.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
setContentView(binding.root)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
@ -41,7 +50,7 @@ class SettingsActivity : AppCompatActivity(),
}
}
setSupportActionBar(findViewById(R.id.toolbar))
setSupportActionBar(binding.toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)

View File

@ -1,14 +1,9 @@
package apps.amine.bou.readerforselfoss.themes
import android.app.Activity
import android.content.Context
import androidx.preference.PreferenceManager
import androidx.annotation.ColorInt
import androidx.appcompat.view.ContextThemeWrapper
import android.util.TypedValue
import androidx.preference.PreferenceManager
import apps.amine.bou.readerforselfoss.R
import android.view.LayoutInflater
import android.view.ViewGroup
class AppColors(a: Activity) {
@ -16,7 +11,6 @@ class AppColors(a: Activity) {
@ColorInt val colorPrimaryDark: Int
@ColorInt val colorAccent: Int
@ColorInt val colorAccentDark: Int
@ColorInt val cardBackgroundColor: Int
@ColorInt val colorBackground: Int
@ColorInt val textColor: Int
val isDarkTheme: Boolean
@ -55,7 +49,7 @@ class AppColors(a: Activity) {
R.color.darkBackground
} else {
a.setTheme(R.style.NoBar)
android.R.color.background_light
R.color.grey_50
}
textColor = if (isDarkTheme) {
@ -63,14 +57,5 @@ class AppColors(a: Activity) {
} else {
R.color.grey_900
}
val wrapper = Context::class.java
val method = wrapper!!.getMethod("getThemeResId")
method.isAccessible = true
val typedCardBackground = TypedValue()
a.theme.resolveAttribute(R.attr.cardBackgroundColor, typedCardBackground, true)
cardBackgroundColor = typedCardBackground.data
}
}

View File

@ -1,43 +0,0 @@
package apps.amine.bou.readerforselfoss.transformers
import androidx.viewpager.widget.ViewPager
import android.view.View
class DepthPageTransformer : ViewPager.PageTransformer {
override fun transformPage(view: View, position: Float) {
val pageWidth = view.width
when {
position < -1 -> // [-Infinity,-1)
// This page is way off-screen to the left.
view.alpha = 0F
position <= 0 -> { // [-1,0]
// Use the default slide transition when moving to the left page
view.alpha = 1F
view.translationX = 0F
view.scaleX = 1F
view.scaleY = 1F
}
position <= 1 -> { // (0,1]
// Fade the page out.
view.alpha = 1 - position
// Counteract the default slide transition
view.translationX = pageWidth * -position
// Scale the page down (between MIN_SCALE and 1)
val scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position))
view.scaleX = scaleFactor
view.scaleY = scaleFactor
}
else -> // (1,+Infinity]
// This page is way off-screen to the right.
view.alpha = 0F
}
}
companion object {
private val MIN_SCALE = 0.75f
}
}

View File

@ -13,7 +13,7 @@ fun String.longHash(): Long {
val chars = this.toCharArray()
for (i in 0 until l) {
h = 31 * h + chars[i].toLong()
h = 31 * h + chars[i].code.toLong()
}
return h
}

View File

@ -4,11 +4,12 @@ import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
import apps.amine.bou.readerforselfoss.LoginActivity
class Config(c: Context) {
val settings: SharedPreferences = c.getSharedPreferences(settingsName, Context.MODE_PRIVATE)
val settings: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(c)
val baseUrl: String
get() = settings.getString("url", "")!!
@ -42,17 +43,15 @@ class Config(c: Context) {
var apiVersion = 0
/* Execute logout and clear all settings to default */
fun logoutAndRedirect(
c: Context,
callingActivity: Activity,
editor: SharedPreferences.Editor,
baseUrlFail: Boolean = false
): Boolean {
editor.remove("url")
editor.remove("login")
editor.remove("password")
editor.remove("apiVersionMajor")
editor.apply()
val settings = PreferenceManager.getDefaultSharedPreferences(c)
settings.edit().clear().commit()
val intent = Intent(c, LoginActivity::class.java)
if (baseUrlFail) {
intent.putExtra("baseUrlFail", baseUrlFail)

View File

@ -86,19 +86,30 @@ fun Context.openItemUrlInternally(
intent.putExtra("currentItem", currentItem)
app.startActivity(intent)
} else {
try {
CustomTabActivityHelper.openCustomTab(
this.openItemUrlInternalBrowser(
linkDecoded,
customTabsIntent,
app)
}
}
fun Context.openItemUrlInternalBrowser(
linkDecoded: String,
customTabsIntent: CustomTabsIntent,
app: Activity
) {
try {
CustomTabActivityHelper.openCustomTab(
app,
customTabsIntent,
Uri.parse(linkDecoded)
) { _, uri ->
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
} catch (e: Exception) {
openInBrowser(linkDecoded, app)
) { _, uri ->
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
} catch (e: Exception) {
openInBrowser(linkDecoded, app)
}
}
@ -121,7 +132,7 @@ fun Context.openItemUrl(
} else {
if (!internalBrowser) {
openInBrowser(linkDecoded, app)
} else {
} else if (articleViewer) {
this.openItemUrlInternally(
allItems,
currentItem,
@ -130,6 +141,12 @@ fun Context.openItemUrl(
articleViewer,
app
)
} else {
this.openItemUrlInternalBrowser(
linkDecoded,
customTabsIntent,
app
)
}
}
}

View File

@ -7,7 +7,7 @@
tools:context="apps.amine.bou.readerforselfoss.AddSourceActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
@ -55,7 +55,8 @@
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="16dp"/>
android:layout_marginLeft="16dp"
android:gravity="center_horizontal" />
<EditText
android:layout_width="match_parent"
@ -67,7 +68,9 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:inputType="text"
android:hint="@string/add_source_hint_name"/>
android:hint="@string/add_source_hint_name"
android:textColorHint="?android:textColorPrimary"
android:autofillHints="false" />
<EditText
android:layout_width="match_parent"
@ -76,10 +79,12 @@
android:ems="10"
android:id="@+id/sourceUri"
android:hint="@string/add_source_hint_url"
android:textColorHint="?android:textColorPrimary"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/nameInput"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
app:layout_constraintLeft_toLeftOf="parent"
android:autofillHints="false" />
<EditText
android:layout_width="match_parent"
@ -91,7 +96,9 @@
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/sourceUri"
android:hint="@string/add_source_hint_tags"
android:inputType="text"/>
android:textColorHint="?android:textColorPrimary"
android:inputType="text"
android:autofillHints="false" />
<Spinner
android:layout_width="match_parent"
@ -100,7 +107,8 @@
app:layout_constraintTop_toBottomOf="@+id/tags"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_height="40dp"/>
android:layout_height="40dp"
android:theme="@style/App.Spinner"/>
<Button
android:text="@string/add_source_save"

View File

@ -21,7 +21,7 @@
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"

View File

@ -22,7 +22,7 @@
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
@ -33,7 +33,7 @@
app:layout_constraintTop_toBottomOf="@+id/appBarLayout" />
<me.relex.circleindicator.CircleIndicator
<me.relex.circleindicator.CircleIndicator3
android:id="@+id/indicator"
android:layout_width="match_parent"
android:layout_height="20dp"

View File

@ -32,7 +32,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom|end"
android:src="@drawable/ic_add_white_24dp"
app:srcCompat="@drawable/ic_add_white_24dp"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:layout_alignParentBottom="true"

View File

@ -16,7 +16,8 @@
app:layout_constraintTop_toTopOf="parent"
card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true"
card_view:layout_constraintBottom_toBottomOf="parent">
card_view:layout_constraintBottom_toBottomOf="parent"
app:cardBackgroundColor="?cardBackgroundColor">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
@ -65,6 +66,7 @@
android:gravity="start"
android:textAlignment="viewStart"
android:textStyle="bold"
android:textColor="?android:textColorPrimary"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="@+id/sourceImage"
app:layout_constraintRight_toRightOf="parent"
@ -79,6 +81,7 @@
android:gravity="start"
android:textAlignment="viewStart"
android:textSize="14sp"
android:textColor="?android:textColorPrimary"
app:layout_constraintLeft_toLeftOf="@+id/title"
app:layout_constraintTop_toBottomOf="@+id/title"
tools:text="Google Actualité Il y a 5h" />

View File

@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:colorBackground"
android:descendantFocusability="blocksDescendants">
<androidx.core.widget.NestedScrollView
@ -33,7 +34,7 @@
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:layout_marginRight="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?android:textColorSecondary"
android:textSize="12sp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
@ -65,6 +66,7 @@
android:layout_marginRight="16dp"
android:layout_marginTop="24dp"
android:paddingBottom="48dp"
android:background="?android:colorBackground"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

View File

@ -12,7 +12,8 @@
android:layout_marginStart="8dp"
android:layout_marginTop="21dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="8dp" />
<TextView
android:id="@+id/title"
@ -29,11 +30,14 @@
android:textAllCaps="false"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="?android:textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/itemImage"
app:layout_constraintTop_toTopOf="parent"
tools:text="Titre" />
tools:text="Titre"
android:layout_marginLeft="8dp"
android:layout_marginRight="16dp" />
<TextView
android:id="@+id/sourceTitleAndDate"
@ -46,10 +50,13 @@
android:maxLines="1"
android:textAlignment="viewStart"
android:textSize="14sp"
android:textColor="?android:textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/itemImage"
app:layout_constraintTop_toTopOf="parent"
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>

View File

@ -26,6 +26,7 @@
android:maxLines="1"
android:textAlignment="textStart"
android:textSize="13sp"
android:textColor="?android:textColorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/deleteBtn"
app:layout_constraintStart_toEndOf="@+id/itemImage"

View File

@ -5,7 +5,7 @@
<color name="colorAccent">#FFff5722</color>
<color name="colorAccentDark">#FFbf360c</color>
<color name="pink">#FFe91e63</color>
<color name="white">#FFFFFFFF</color>
<color name="white">#FFFFFF</color>
<color name="black">#FF000000</color>
<color name="red">#FF0000</color>
<color name="refresh_progress_1">@color/colorAccentDark</color>
@ -20,5 +20,5 @@
<color name="cardBackgroundColor">#FFFFFFFF</color>
<color name="materialDrawerHeaderSelectionText">#212121</color>
<color name="darkBackground">#FF303030</color>
<color name="darkBackground">#303030</color>
</resources>

View File

@ -28,6 +28,7 @@
<item name="cardBackgroundColor">@color/grey_800</item>
<item name="android:colorBackground">@color/darkBackground</item>
<item name="colorSurface">@color/darkBackground</item>
<item name="alertDialogTheme">@style/AlertDialogDark</item>
<item name="bnbBackgroundColor">@color/grey_900</item>
<item name="android:textColorPrimary">@color/white</item>
<item name="android:textColorSecondary">@color/grey_600</item>
@ -58,4 +59,15 @@
<item name="android:tint">?android:textColorPrimary</item>
</style>
<!-- Spinner Theme -->
<style name="App.Spinner" parent="Widget.AppCompat.Light.DropDownItem.Spinner">
<item name="android:textColor">?android:textColorPrimary</item>
</style>
<!-- Alert dialog Theme -->
<style name="AlertDialogDark" parent="Theme.MaterialComponents.Dialog">
<item name="android:background">@color/darkBackground</item>
</style>
</resources>

View File

@ -2,7 +2,7 @@
buildscript {
ext {
kotlin_version = '1.5.31'
kotlin_version = '1.6.10'
android_version = '1.0.0'
androidx_version = '1.1.0-alpha05'
lifecycle_version = '2.2.0-alpha01'
@ -15,7 +15,7 @@ buildscript {
maven { url "https://www.jitpack.io" }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.3'
classpath 'com.android.tools.build:gradle:7.0.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
@ -23,9 +23,9 @@ buildscript {
allprojects {
repositories {
google()
mavenCentral()
jcenter()
maven { url "https://www.jitpack.io" }
mavenCentral()
}
}