Compare commits
No commits in common. "15ec0f2d269caa686cb4505bc17a39608647cdd4" and "4781e30da2ed39b106e494380b9f6ac3cfdd57dd" have entirely different histories.
15ec0f2d26
...
4781e30da2
11
.drone.yml
11
.drone.yml
@ -3,23 +3,14 @@ type: docker
|
|||||||
name: test
|
name: test
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Anylyse
|
- name: AnylyseBuildTest
|
||||||
image: mingc/android-build-box:latest
|
image: mingc/android-build-box:latest
|
||||||
failure: ignore
|
failure: ignore
|
||||||
detach: true
|
|
||||||
commands:
|
commands:
|
||||||
- echo "---------------------------------------------------------"
|
- echo "---------------------------------------------------------"
|
||||||
- echo "Analysing..."
|
- echo "Analysing..."
|
||||||
- ./gradlew sonarqube -Dsonar.projectKey=RFS2 -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\""
|
- ./gradlew sonarqube -Dsonar.projectKey=RFS2 -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\""
|
||||||
- echo "---------------------------------------------------------"
|
- echo "---------------------------------------------------------"
|
||||||
environment:
|
|
||||||
SONAR_HOST_URL:
|
|
||||||
from_secret: sonarScannerHostUrl
|
|
||||||
SONAR_LOGIN:
|
|
||||||
from_secret: sonarScannerLogin
|
|
||||||
- name: BuildAndTest
|
|
||||||
image: mingc/android-build-box:latest
|
|
||||||
commands:
|
|
||||||
- echo "Building..."
|
- echo "Building..."
|
||||||
- ./gradlew :androidApp:build -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
|
- ./gradlew :androidApp:build -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
|
||||||
- echo "---------------------------------------------------------"
|
- echo "---------------------------------------------------------"
|
||||||
|
@ -30,7 +30,7 @@ fun gitVersion(): String {
|
|||||||
println("Tag found on current commit")
|
println("Tag found on current commit")
|
||||||
execWithOutput("git -C ../ describe --contains HEAD")
|
execWithOutput("git -C ../ describe --contains HEAD")
|
||||||
}
|
}
|
||||||
return process.replace("^0", "").replace("'", "").substring(1).replace("\\.", "").trim()
|
return process.replace("'", "").substring(1).replace("\\.", "").trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun versionCodeFromGit(): Int {
|
fun versionCodeFromGit(): Int {
|
||||||
@ -129,6 +129,7 @@ dependencies {
|
|||||||
implementation("androidx.recyclerview:recyclerview:1.3.0-alpha01")
|
implementation("androidx.recyclerview:recyclerview:1.3.0-alpha01")
|
||||||
implementation("androidx.legacy:legacy-support-v4:1.0.0")
|
implementation("androidx.legacy:legacy-support-v4:1.0.0")
|
||||||
implementation("androidx.vectordrawable:vectordrawable:1.2.0-alpha02")
|
implementation("androidx.vectordrawable:vectordrawable:1.2.0-alpha02")
|
||||||
|
implementation("androidx.browser:browser:1.4.0")
|
||||||
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")
|
||||||
@ -166,6 +167,8 @@ dependencies {
|
|||||||
implementation("com.mikepenz:materialdrawer:8.4.5")
|
implementation("com.mikepenz:materialdrawer:8.4.5")
|
||||||
|
|
||||||
// Themes
|
// Themes
|
||||||
|
implementation("com.52inc:scoops:1.0.0")
|
||||||
|
implementation("com.jaredrummler:colorpicker:1.1.0")
|
||||||
implementation("com.github.rubensousa:floatingtoolbar:1.5.1")
|
implementation("com.github.rubensousa:floatingtoolbar:1.5.1")
|
||||||
|
|
||||||
// Pager
|
// Pager
|
||||||
|
@ -7,10 +7,13 @@ import android.widget.*
|
|||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.ActivityAddSourceBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.ActivityAddSourceBinding
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.Toppings
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlInvalid
|
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlInvalid
|
||||||
import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException
|
import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
|
import com.ftinc.scoop.Scoop
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -23,6 +26,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware {
|
|||||||
|
|
||||||
private var mSpoutsValue: String? = null
|
private var mSpoutsValue: String? = null
|
||||||
|
|
||||||
|
private lateinit var appColors: AppColors
|
||||||
private lateinit var binding: ActivityAddSourceBinding
|
private lateinit var binding: ActivityAddSourceBinding
|
||||||
|
|
||||||
override val di by closestDI()
|
override val di by closestDI()
|
||||||
@ -30,18 +34,43 @@ class AddSourceActivity : AppCompatActivity(), DIAware {
|
|||||||
private val appSettingsService : AppSettingsService by instance()
|
private val appSettingsService : AppSettingsService by instance()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
appColors = AppColors(this@AddSourceActivity)
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivityAddSourceBinding.inflate(layoutInflater)
|
binding = ActivityAddSourceBinding.inflate(layoutInflater)
|
||||||
val view = binding.root
|
val view = binding.root
|
||||||
|
|
||||||
setContentView(view)
|
setContentView(view)
|
||||||
|
|
||||||
|
val scoop = Scoop.getInstance()
|
||||||
|
scoop.bind(this, Toppings.PRIMARY.value, binding.toolbar)
|
||||||
|
scoop.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
|
||||||
|
|
||||||
|
val drawable = binding.nameInput.background
|
||||||
|
drawable.setTint(appColors.colorAccent)
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: clean
|
||||||
|
binding.nameInput.background = drawable
|
||||||
|
|
||||||
|
val drawable1 = binding.sourceUri.background
|
||||||
|
drawable1.setTint(appColors.colorAccent)
|
||||||
|
|
||||||
|
binding.sourceUri.background = drawable1
|
||||||
|
|
||||||
|
val drawable2 = binding.tags.background
|
||||||
|
drawable2.setTint(appColors.colorAccent)
|
||||||
|
|
||||||
|
binding.tags.background = drawable2
|
||||||
|
|
||||||
setSupportActionBar(binding.toolbar)
|
setSupportActionBar(binding.toolbar)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
|
||||||
maybeGetDetailsFromIntentSharing(intent, binding.sourceUri, binding.nameInput)
|
maybeGetDetailsFromIntentSharing(intent, binding.sourceUri, binding.nameInput)
|
||||||
|
|
||||||
|
binding.saveBtn.setTextColor(appColors.colorAccent)
|
||||||
|
|
||||||
binding.saveBtn.setOnClickListener {
|
binding.saveBtn.setOnClickListener {
|
||||||
handleSaveSource(
|
handleSaveSource(
|
||||||
binding.tags,
|
binding.tags,
|
||||||
@ -55,7 +84,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware {
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
val baseUrl = appSettingsService.getBaseUrl()
|
val baseUrl = appSettingsService.getBaseUrl()
|
||||||
if (baseUrl.isEmpty() || baseUrl.isBaseUrlInvalid()) {
|
if (baseUrl.isEmpty() || baseUrl.isBaseUrlInvalid(this@AddSourceActivity)) {
|
||||||
mustLoginToAddSource()
|
mustLoginToAddSource()
|
||||||
} else {
|
} else {
|
||||||
handleSpoutsSpinner(binding.spoutsSpinner, binding.progress, binding.formContainer)
|
handleSpoutsSpinner(binding.spoutsSpinner, binding.progress, binding.formContainer)
|
||||||
|
@ -15,9 +15,6 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
|
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.view.doOnNextLayout
|
import androidx.core.view.doOnNextLayout
|
||||||
import androidx.drawerlayout.widget.DrawerLayout
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
@ -32,8 +29,11 @@ import bou.amine.apps.readerforselfossv2.android.adapters.ItemsAdapter
|
|||||||
import bou.amine.apps.readerforselfossv2.android.background.LoadingWorker
|
import bou.amine.apps.readerforselfossv2.android.background.LoadingWorker
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.ActivityHomeBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.ActivityHomeBinding
|
||||||
import bou.amine.apps.readerforselfossv2.android.settings.SettingsActivity
|
import bou.amine.apps.readerforselfossv2.android.settings.SettingsActivity
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.Toppings
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.bottombar.maybeShow
|
import bou.amine.apps.readerforselfossv2.android.utils.bottombar.maybeShow
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.bottombar.removeBadge
|
import bou.amine.apps.readerforselfossv2.android.utils.bottombar.removeBadge
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
@ -43,6 +43,7 @@ import com.ashokvarma.bottomnavigation.BottomNavigationItem
|
|||||||
import com.ashokvarma.bottomnavigation.TextBadgeItem
|
import com.ashokvarma.bottomnavigation.TextBadgeItem
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import com.ftinc.scoop.Scoop
|
||||||
import com.mikepenz.aboutlibraries.LibsBuilder
|
import com.mikepenz.aboutlibraries.LibsBuilder
|
||||||
import com.mikepenz.materialdrawer.holder.BadgeStyle
|
import com.mikepenz.materialdrawer.holder.BadgeStyle
|
||||||
import com.mikepenz.materialdrawer.holder.ColorHolder
|
import com.mikepenz.materialdrawer.holder.ColorHolder
|
||||||
@ -79,6 +80,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
private lateinit var tabNewBadge: TextBadgeItem
|
private lateinit var tabNewBadge: TextBadgeItem
|
||||||
private lateinit var tabArchiveBadge: TextBadgeItem
|
private lateinit var tabArchiveBadge: TextBadgeItem
|
||||||
private lateinit var tabStarredBadge: TextBadgeItem
|
private lateinit var tabStarredBadge: TextBadgeItem
|
||||||
|
private lateinit var customTabActivityHelper: CustomTabActivityHelper
|
||||||
|
private lateinit var appColors: AppColors
|
||||||
private var offset: Int = 0
|
private var offset: Int = 0
|
||||||
private var firstVisible: Int = 0
|
private var firstVisible: Int = 0
|
||||||
private lateinit var recyclerViewScrollListener: RecyclerView.OnScrollListener
|
private lateinit var recyclerViewScrollListener: RecyclerView.OnScrollListener
|
||||||
@ -100,7 +103,16 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
|
|
||||||
data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?)
|
data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?)
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
customTabActivityHelper.bindCustomTabsService(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
||||||
|
// Add appcolors to DI
|
||||||
|
appColors = AppColors(this@HomeActivity)
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivityHomeBinding.inflate(layoutInflater)
|
binding = ActivityHomeBinding.inflate(layoutInflater)
|
||||||
val view = binding.root
|
val view = binding.root
|
||||||
@ -114,6 +126,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
|
|
||||||
setContentView(view)
|
setContentView(view)
|
||||||
|
|
||||||
|
handleThemeBinding()
|
||||||
|
|
||||||
setSupportActionBar(binding.toolBar)
|
setSupportActionBar(binding.toolBar)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.setHomeButtonEnabled(true)
|
supportActionBar?.setHomeButtonEnabled(true)
|
||||||
@ -121,16 +135,18 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
binding.drawerContainer.addDrawerListener(mDrawerToggle)
|
binding.drawerContainer.addDrawerListener(mDrawerToggle)
|
||||||
mDrawerToggle.syncState()
|
mDrawerToggle.syncState()
|
||||||
|
|
||||||
|
customTabActivityHelper = CustomTabActivityHelper()
|
||||||
|
|
||||||
handleBottomBar()
|
handleBottomBar()
|
||||||
initDrawer()
|
initDrawer()
|
||||||
|
|
||||||
handleSwipeRefreshLayout()
|
handleSwipeRefreshLayout()
|
||||||
|
|
||||||
|
getElementsAccordingToTab()
|
||||||
|
|
||||||
if (appSettingsService.isItemCachingEnabled()) {
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
repository.tryToCacheItemsAndGetNewOnes()
|
repository.tryToCacheItemsAndGetNewOnes()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,24 +233,27 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
tabNewBadge = TextBadgeItem()
|
tabNewBadge = TextBadgeItem()
|
||||||
.setText("")
|
.setText("")
|
||||||
.setHideOnSelect(false).hide(false)
|
.setHideOnSelect(false).hide(false)
|
||||||
|
.setBackgroundColor(appColors.colorPrimary)
|
||||||
tabArchiveBadge = TextBadgeItem()
|
tabArchiveBadge = TextBadgeItem()
|
||||||
.setText("")
|
.setText("")
|
||||||
.setHideOnSelect(false).hide(false)
|
.setHideOnSelect(false).hide(false)
|
||||||
|
.setBackgroundColor(appColors.colorPrimary)
|
||||||
tabStarredBadge = TextBadgeItem()
|
tabStarredBadge = TextBadgeItem()
|
||||||
.setText("")
|
.setText("")
|
||||||
.setHideOnSelect(false).hide(false)
|
.setHideOnSelect(false).hide(false)
|
||||||
|
.setBackgroundColor(appColors.colorPrimary)
|
||||||
|
|
||||||
val tabNew =
|
val tabNew =
|
||||||
BottomNavigationItem(
|
BottomNavigationItem(
|
||||||
R.drawable.ic_tab_fiber_new_black_24dp,
|
R.drawable.ic_tab_fiber_new_black_24dp,
|
||||||
getString(R.string.tab_new)
|
getString(R.string.tab_new)
|
||||||
)
|
).setActiveColor(appColors.colorAccent)
|
||||||
.setBadgeItem(tabNewBadge)
|
.setBadgeItem(tabNewBadge)
|
||||||
val tabArchive =
|
val tabArchive =
|
||||||
BottomNavigationItem(
|
BottomNavigationItem(
|
||||||
R.drawable.ic_tab_archive_black_24dp,
|
R.drawable.ic_tab_archive_black_24dp,
|
||||||
getString(R.string.tab_read)
|
getString(R.string.tab_read)
|
||||||
)
|
).setActiveColor(appColors.colorAccentDark)
|
||||||
.setBadgeItem(tabArchiveBadge)
|
.setBadgeItem(tabArchiveBadge)
|
||||||
val tabStarred =
|
val tabStarred =
|
||||||
BottomNavigationItem(
|
BottomNavigationItem(
|
||||||
@ -250,6 +269,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
.setFirstSelectedPosition(0)
|
.setFirstSelectedPosition(0)
|
||||||
.initialise()
|
.initialise()
|
||||||
binding.bottomBar.setMode(BottomNavigationBar.MODE_SHIFTING)
|
binding.bottomBar.setMode(BottomNavigationBar.MODE_SHIFTING)
|
||||||
|
binding.bottomBar.setBackgroundStyle(BottomNavigationBar.BACKGROUND_STYLE_STATIC)
|
||||||
|
|
||||||
if (fromTabShortcut) {
|
if (fromTabShortcut) {
|
||||||
binding.bottomBar.selectTab(elementsShown.position - 1)
|
binding.bottomBar.selectTab(elementsShown.position - 1)
|
||||||
@ -259,8 +279,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
|
appColors = AppColors(this@HomeActivity)
|
||||||
|
|
||||||
handleDrawerItems()
|
handleDrawerItems()
|
||||||
|
|
||||||
|
handleThemeUpdate()
|
||||||
|
|
||||||
reloadLayoutManager()
|
reloadLayoutManager()
|
||||||
|
|
||||||
if (appSettingsService.isInfiniteLoadingEnabled()) {
|
if (appSettingsService.isInfiniteLoadingEnabled()) {
|
||||||
@ -280,6 +304,25 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
getElementsAccordingToTab()
|
getElementsAccordingToTab()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
customTabActivityHelper.unbindCustomTabsService(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleThemeBinding() {
|
||||||
|
val scoop = Scoop.getInstance()
|
||||||
|
scoop.bind(this, Toppings.PRIMARY.value, binding.toolBar)
|
||||||
|
scoop.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleThemeUpdate() {
|
||||||
|
|
||||||
|
val scoop = Scoop.getInstance()
|
||||||
|
scoop.update(Toppings.PRIMARY.value, appColors.colorPrimary)
|
||||||
|
|
||||||
|
scoop.update(Toppings.PRIMARY_DARK.value, appColors.colorPrimaryDark)
|
||||||
|
}
|
||||||
|
|
||||||
private fun initDrawer() {
|
private fun initDrawer() {
|
||||||
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
|
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
|
||||||
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
|
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
|
||||||
@ -464,7 +507,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
val gdColor = try {
|
val gdColor = try {
|
||||||
Color.parseColor(it.color)
|
Color.parseColor(it.color)
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
resources.getColor(R.color.colorPrimary)
|
appColors.colorPrimary
|
||||||
}
|
}
|
||||||
gd.setColor(gdColor)
|
gd.setColor(gdColor)
|
||||||
gd.shape = GradientDrawable.RECTANGLE
|
gd.shape = GradientDrawable.RECTANGLE
|
||||||
@ -478,7 +521,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
iconDrawable = gd
|
iconDrawable = gd
|
||||||
badgeStyle = BadgeStyle().apply {
|
badgeStyle = BadgeStyle().apply {
|
||||||
textColor = ColorHolder.fromColor(Color.WHITE)
|
textColor = ColorHolder.fromColor(Color.WHITE)
|
||||||
color = ColorHolder.fromColor(resources.getColor(R.color.colorAccent))
|
color = ColorHolder.fromColor(appColors.colorAccent)
|
||||||
}
|
}
|
||||||
onDrawerItemClickListener = { _, _, _ ->
|
onDrawerItemClickListener = { _, _, _ ->
|
||||||
repository.tagFilter = it
|
repository.tagFilter = it
|
||||||
@ -701,6 +744,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
ItemCardAdapter(
|
ItemCardAdapter(
|
||||||
this,
|
this,
|
||||||
items,
|
items,
|
||||||
|
customTabActivityHelper,
|
||||||
|
appColors,
|
||||||
) {
|
) {
|
||||||
updateItems(it)
|
updateItems(it)
|
||||||
}
|
}
|
||||||
@ -709,6 +754,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
ItemListAdapter(
|
ItemListAdapter(
|
||||||
this,
|
this,
|
||||||
items,
|
items,
|
||||||
|
customTabActivityHelper,
|
||||||
|
appColors,
|
||||||
) {
|
) {
|
||||||
updateItems(it)
|
updateItems(it)
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,8 @@ import android.view.inputmethod.EditorInfo
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.ActivityLoginBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.ActivityLoginBinding
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlInvalid
|
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlInvalid
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
@ -30,6 +30,7 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
|||||||
private var inValidCount: Int = 0
|
private var inValidCount: Int = 0
|
||||||
private var isWithLogin = false
|
private var isWithLogin = false
|
||||||
|
|
||||||
|
private lateinit var appColors: AppColors
|
||||||
private lateinit var binding: ActivityLoginBinding
|
private lateinit var binding: ActivityLoginBinding
|
||||||
|
|
||||||
override val di by closestDI()
|
override val di by closestDI()
|
||||||
@ -37,9 +38,9 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
|||||||
private val appSettingsService : AppSettingsService by instance()
|
private val appSettingsService : AppSettingsService by instance()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
appColors = AppColors(this@LoginActivity)
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
|
||||||
|
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivityLoginBinding.inflate(layoutInflater)
|
binding = ActivityLoginBinding.inflate(layoutInflater)
|
||||||
val view = binding.root
|
val view = binding.root
|
||||||
|
|
||||||
@ -121,7 +122,7 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
|||||||
var cancel = false
|
var cancel = false
|
||||||
var focusView: View? = null
|
var focusView: View? = null
|
||||||
|
|
||||||
if (url.isBaseUrlInvalid()) {
|
if (url.isBaseUrlInvalid(this@LoginActivity)) {
|
||||||
binding.urlView.error = getString(R.string.login_url_problem)
|
binding.urlView.error = getString(R.string.login_url_problem)
|
||||||
focusView = binding.urlView
|
focusView = binding.urlView
|
||||||
cancel = true
|
cancel = true
|
||||||
|
@ -21,6 +21,7 @@ import bou.amine.apps.readerforselfossv2.repository.Repository
|
|||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import com.ftinc.scoop.Scoop
|
||||||
import com.github.ln_12.library.ConnectivityStatus
|
import com.github.ln_12.library.ConnectivityStatus
|
||||||
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
|
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
|
||||||
import com.mikepenz.materialdrawer.util.DrawerImageLoader
|
import com.mikepenz.materialdrawer.util.DrawerImageLoader
|
||||||
@ -53,6 +54,8 @@ class MyApp : MultiDexApplication(), DIAware {
|
|||||||
|
|
||||||
initDrawerImageLoader()
|
initDrawerImageLoader()
|
||||||
|
|
||||||
|
initTheme()
|
||||||
|
|
||||||
tryToHandleBug()
|
tryToHandleBug()
|
||||||
|
|
||||||
handleNotificationChannels()
|
handleNotificationChannels()
|
||||||
@ -114,6 +117,14 @@ class MyApp : MultiDexApplication(), DIAware {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initTheme() {
|
||||||
|
Scoop.waffleCone()
|
||||||
|
.addFlavor(getString(R.string.default_theme), R.style.NoBar, true)
|
||||||
|
.addFlavor(getString(R.string.default_dark_theme), R.style.NoBarDark, false)
|
||||||
|
.setSharedPreferences(PreferenceManager.getDefaultSharedPreferences(this))
|
||||||
|
.initialize()
|
||||||
|
}
|
||||||
|
|
||||||
private fun tryToHandleBug() {
|
private fun tryToHandleBug() {
|
||||||
val oldHandler = Thread.getDefaultUncaughtExceptionHandler()
|
val oldHandler = Thread.getDefaultUncaughtExceptionHandler()
|
||||||
|
|
||||||
|
@ -12,9 +12,12 @@ import androidx.viewpager2.adapter.FragmentStateAdapter
|
|||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.ActivityReaderBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.ActivityReaderBinding
|
||||||
import bou.amine.apps.readerforselfossv2.android.fragments.ArticleFragment
|
import bou.amine.apps.readerforselfossv2.android.fragments.ArticleFragment
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.Toppings
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
|
import com.ftinc.scoop.Scoop
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -25,6 +28,7 @@ import org.kodein.di.instance
|
|||||||
class ReaderActivity : AppCompatActivity(), DIAware {
|
class ReaderActivity : AppCompatActivity(), DIAware {
|
||||||
|
|
||||||
private var currentItem: Int = 0
|
private var currentItem: Int = 0
|
||||||
|
private lateinit var appColors: AppColors
|
||||||
|
|
||||||
private lateinit var toolbarMenu: Menu
|
private lateinit var toolbarMenu: Menu
|
||||||
|
|
||||||
@ -52,11 +56,16 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
appColors = AppColors(this)
|
||||||
binding = ActivityReaderBinding.inflate(layoutInflater)
|
binding = ActivityReaderBinding.inflate(layoutInflater)
|
||||||
val view = binding.root
|
val view = binding.root
|
||||||
|
|
||||||
setContentView(view)
|
setContentView(view)
|
||||||
|
|
||||||
|
val scoop = Scoop.getInstance()
|
||||||
|
scoop.bind(this, Toppings.PRIMARY.value, binding.toolBar)
|
||||||
|
scoop.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
|
||||||
|
|
||||||
setSupportActionBar(binding.toolBar)
|
setSupportActionBar(binding.toolBar)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
@ -8,8 +8,11 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import bou.amine.apps.readerforselfossv2.android.adapters.SourcesListAdapter
|
import bou.amine.apps.readerforselfossv2.android.adapters.SourcesListAdapter
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySourcesBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySourcesBinding
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.Toppings
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
|
import com.ftinc.scoop.Scoop
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -19,15 +22,21 @@ import org.kodein.di.instance
|
|||||||
|
|
||||||
class SourcesActivity : AppCompatActivity(), DIAware {
|
class SourcesActivity : AppCompatActivity(), DIAware {
|
||||||
|
|
||||||
|
private lateinit var appColors: AppColors
|
||||||
private lateinit var binding: ActivitySourcesBinding
|
private lateinit var binding: ActivitySourcesBinding
|
||||||
|
|
||||||
override val di by closestDI()
|
override val di by closestDI()
|
||||||
private val repository : Repository by instance()
|
private val repository : Repository by instance()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
appColors = AppColors(this@SourcesActivity)
|
||||||
binding = ActivitySourcesBinding.inflate(layoutInflater)
|
binding = ActivitySourcesBinding.inflate(layoutInflater)
|
||||||
val view = binding.root
|
val view = binding.root
|
||||||
|
|
||||||
|
val scoop = Scoop.getInstance()
|
||||||
|
scoop.bind(this, Toppings.PRIMARY.value, binding.toolbar)
|
||||||
|
scoop.bindStatusBar(this, Toppings.PRIMARY_DARK.value)
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setContentView(view)
|
setContentView(view)
|
||||||
@ -36,8 +45,8 @@ class SourcesActivity : AppCompatActivity(), DIAware {
|
|||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
|
||||||
binding.fab.rippleColor = resources.getColor(R.color.colorAccentDark)
|
binding.fab.rippleColor = appColors.colorAccentDark
|
||||||
binding.fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent))
|
binding.fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
|
@ -10,7 +10,9 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import bou.amine.apps.readerforselfossv2.android.R
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding
|
||||||
import bou.amine.apps.readerforselfossv2.android.model.toTextDrawableString
|
import bou.amine.apps.readerforselfossv2.android.model.toTextDrawableString
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.*
|
import bou.amine.apps.readerforselfossv2.android.utils.*
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop
|
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable
|
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
@ -32,6 +34,8 @@ import org.kodein.di.instance
|
|||||||
class ItemCardAdapter(
|
class ItemCardAdapter(
|
||||||
override val app: Activity,
|
override val app: Activity,
|
||||||
override var items: ArrayList<SelfossModel.Item>,
|
override var items: ArrayList<SelfossModel.Item>,
|
||||||
|
private val helper: CustomTabActivityHelper,
|
||||||
|
override val appColors: AppColors,
|
||||||
override val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
override val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
||||||
) : ItemsAdapter<ItemCardAdapter.ViewHolder>() {
|
) : ItemsAdapter<ItemCardAdapter.ViewHolder>() {
|
||||||
private val c: Context = app.baseContext
|
private val c: Context = app.baseContext
|
||||||
@ -40,8 +44,8 @@ class ItemCardAdapter(
|
|||||||
c.resources.getDimension(R.dimen.card_image_max_height).toInt()
|
c.resources.getDimension(R.dimen.card_image_max_height).toInt()
|
||||||
|
|
||||||
override val di: DI by closestDI(app)
|
override val di: DI by closestDI(app)
|
||||||
override val repository: Repository by instance()
|
override val repository : Repository by instance()
|
||||||
override val appSettingsService: AppSettingsService by instance()
|
override val appSettingsService : AppSettingsService by instance()
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val binding = CardItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
val binding = CardItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
@ -57,7 +61,7 @@ class ItemCardAdapter(
|
|||||||
|
|
||||||
binding.title.setOnTouchListener(LinkOnTouchListener())
|
binding.title.setOnTouchListener(LinkOnTouchListener())
|
||||||
|
|
||||||
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
binding.title.setLinkTextColor(appColors.colorAccent)
|
||||||
|
|
||||||
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
|
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
|
||||||
|
|
||||||
@ -79,10 +83,10 @@ class ItemCardAdapter(
|
|||||||
val color = generator.getColor(itm.title.getHtmlDecoded())
|
val color = generator.getColor(itm.title.getHtmlDecoded())
|
||||||
|
|
||||||
val drawable =
|
val drawable =
|
||||||
TextDrawable
|
TextDrawable
|
||||||
.builder()
|
.builder()
|
||||||
.round()
|
.round()
|
||||||
.build(itm.title.getHtmlDecoded().toTextDrawableString(), color)
|
.build(itm.title.getHtmlDecoded().toTextDrawableString(), color)
|
||||||
binding.sourceImage.setImageDrawable(drawable)
|
binding.sourceImage.setImageDrawable(drawable)
|
||||||
} else {
|
} else {
|
||||||
c.circularBitmapDrawable(itm.getIcon(repository.baseUrl), binding.sourceImage)
|
c.circularBitmapDrawable(itm.getIcon(repository.baseUrl), binding.sourceImage)
|
||||||
@ -97,7 +101,7 @@ class ItemCardAdapter(
|
|||||||
inner class ViewHolder(val binding: CardItemBinding) : RecyclerView.ViewHolder(binding.root) {
|
inner class ViewHolder(val binding: CardItemBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||||
init {
|
init {
|
||||||
handleClickListeners()
|
handleClickListeners()
|
||||||
handleLinkOpening()
|
handleCustomTabActions()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleClickListeners() {
|
private fun handleClickListeners() {
|
||||||
@ -107,34 +111,41 @@ class ItemCardAdapter(
|
|||||||
if (item.starred) {
|
if (item.starred) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
repository.unstarr(item)
|
repository.unstarr(item)
|
||||||
|
// TODO: Handle failure
|
||||||
}
|
}
|
||||||
item.starred = false
|
item.starred = false
|
||||||
binding.favButton.isSelected = false
|
binding.favButton.isSelected = false
|
||||||
} else {
|
} else {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
repository.starr(item)
|
repository.starr(item)
|
||||||
|
// TODO: Handle failure
|
||||||
}
|
}
|
||||||
item.starred = true
|
item.starred = true
|
||||||
binding.favButton.isSelected = true
|
binding.favButton.isSelected = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.shareBtn.setOnClickListener {
|
binding.shareBtn.setOnClickListener {
|
||||||
val item = items[bindingAdapterPosition]
|
val item = items[bindingAdapterPosition]
|
||||||
c.shareLink(item.getLinkDecoded(), item.title.getHtmlDecoded())
|
c.shareLink(item.getLinkDecoded(), item.title.getHtmlDecoded())
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.browserBtn.setOnClickListener {
|
||||||
|
c.openInBrowserAsNewTask(items[bindingAdapterPosition])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.browserBtn.setOnClickListener {
|
private fun handleCustomTabActions() {
|
||||||
c.openInBrowserAsNewTask(items[bindingAdapterPosition])
|
val customTabsIntent = c.buildCustomTabsIntent()
|
||||||
}
|
helper.bindCustomTabsService(app)
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleLinkOpening() {
|
|
||||||
binding.root.setOnClickListener {
|
binding.root.setOnClickListener {
|
||||||
c.openItemUrl(
|
c.openItemUrl(
|
||||||
items,
|
items,
|
||||||
bindingAdapterPosition,
|
bindingAdapterPosition,
|
||||||
items[bindingAdapterPosition].getLinkDecoded(),
|
items[bindingAdapterPosition].getLinkDecoded(),
|
||||||
|
customTabsIntent,
|
||||||
|
appSettingsService.isInternalBrowserEnabled(),
|
||||||
appSettingsService.isArticleViewerEnabled(),
|
appSettingsService.isArticleViewerEnabled(),
|
||||||
app
|
app
|
||||||
)
|
)
|
||||||
|
@ -5,10 +5,12 @@ import android.content.Context
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import bou.amine.apps.readerforselfossv2.android.R
|
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.ListItemBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.ListItemBinding
|
||||||
import bou.amine.apps.readerforselfossv2.android.model.toTextDrawableString
|
import bou.amine.apps.readerforselfossv2.android.model.toTextDrawableString
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.LinkOnTouchListener
|
import bou.amine.apps.readerforselfossv2.android.utils.LinkOnTouchListener
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.buildCustomTabsIntent
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop
|
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable
|
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.openItemUrl
|
import bou.amine.apps.readerforselfossv2.android.utils.openItemUrl
|
||||||
@ -27,6 +29,8 @@ import org.kodein.di.instance
|
|||||||
class ItemListAdapter(
|
class ItemListAdapter(
|
||||||
override val app: Activity,
|
override val app: Activity,
|
||||||
override var items: ArrayList<SelfossModel.Item>,
|
override var items: ArrayList<SelfossModel.Item>,
|
||||||
|
private val helper: CustomTabActivityHelper,
|
||||||
|
override val appColors: AppColors,
|
||||||
override val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
override val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
||||||
) : ItemsAdapter<ItemListAdapter.ViewHolder>() {
|
) : ItemsAdapter<ItemListAdapter.ViewHolder>() {
|
||||||
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
private val generator: ColorGenerator = ColorGenerator.MATERIAL
|
||||||
@ -49,7 +53,7 @@ class ItemListAdapter(
|
|||||||
|
|
||||||
binding.title.setOnTouchListener(LinkOnTouchListener())
|
binding.title.setOnTouchListener(LinkOnTouchListener())
|
||||||
|
|
||||||
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
binding.title.setLinkTextColor(appColors.colorAccent)
|
||||||
|
|
||||||
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
|
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
|
||||||
|
|
||||||
@ -79,15 +83,20 @@ class ItemListAdapter(
|
|||||||
inner class ViewHolder(val binding: ListItemBinding) : RecyclerView.ViewHolder(binding.root) {
|
inner class ViewHolder(val binding: ListItemBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
handleLinkOpening()
|
handleCustomTabActions()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleLinkOpening() {
|
private fun handleCustomTabActions() {
|
||||||
|
val customTabsIntent = c.buildCustomTabsIntent()
|
||||||
|
helper.bindCustomTabsService(app)
|
||||||
|
|
||||||
binding.root.setOnClickListener {
|
binding.root.setOnClickListener {
|
||||||
c.openItemUrl(
|
c.openItemUrl(
|
||||||
items,
|
items,
|
||||||
bindingAdapterPosition,
|
bindingAdapterPosition,
|
||||||
items[bindingAdapterPosition].getLinkDecoded(),
|
items[bindingAdapterPosition].getLinkDecoded(),
|
||||||
|
customTabsIntent,
|
||||||
|
appSettingsService.isInternalBrowserEnabled(),
|
||||||
appSettingsService.isArticleViewerEnabled(),
|
appSettingsService.isArticleViewerEnabled(),
|
||||||
app
|
app
|
||||||
)
|
)
|
||||||
|
@ -5,6 +5,7 @@ import android.graphics.Color
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import bou.amine.apps.readerforselfossv2.android.R
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
@ -20,6 +21,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
|
|||||||
abstract val repository: Repository
|
abstract val repository: Repository
|
||||||
abstract val appSettingsService: AppSettingsService
|
abstract val appSettingsService: AppSettingsService
|
||||||
abstract val app: Activity
|
abstract val app: Activity
|
||||||
|
abstract val appColors: AppColors
|
||||||
abstract val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
abstract val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
||||||
|
|
||||||
fun updateAllItems(items: ArrayList<SelfossModel.Item>) {
|
fun updateAllItems(items: ArrayList<SelfossModel.Item>) {
|
||||||
@ -28,7 +30,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
|
|||||||
updateItems(this.items)
|
updateItems(this.items)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unmarkSnackbar(position: Int) {
|
private fun unmarkSnackbar(i: SelfossModel.Item, position: Int) {
|
||||||
val s = Snackbar
|
val s = Snackbar
|
||||||
.make(
|
.make(
|
||||||
app.findViewById(R.id.coordLayout),
|
app.findViewById(R.id.coordLayout),
|
||||||
@ -85,7 +87,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
|
|||||||
notifyItemChanged(position)
|
notifyItemChanged(position)
|
||||||
}
|
}
|
||||||
if (showSnackbar) {
|
if (showSnackbar) {
|
||||||
unmarkSnackbar(position)
|
unmarkSnackbar(i, position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import android.graphics.Typeface
|
|||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.webkit.WebResourceResponse
|
import android.webkit.WebResourceResponse
|
||||||
import android.webkit.WebSettings
|
import android.webkit.WebSettings
|
||||||
@ -16,6 +15,7 @@ import android.webkit.WebView
|
|||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.browser.customtabs.CustomTabsIntent
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.core.widget.NestedScrollView
|
import androidx.core.widget.NestedScrollView
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
@ -27,8 +27,12 @@ import bou.amine.apps.readerforselfossv2.android.databinding.FragmentArticleBind
|
|||||||
import bou.amine.apps.readerforselfossv2.android.model.ParecelableItem
|
import bou.amine.apps.readerforselfossv2.android.model.ParecelableItem
|
||||||
import bou.amine.apps.readerforselfossv2.android.model.toModel
|
import bou.amine.apps.readerforselfossv2.android.model.toModel
|
||||||
import bou.amine.apps.readerforselfossv2.android.model.toParcelable
|
import bou.amine.apps.readerforselfossv2.android.model.toParcelable
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.buildCustomTabsIntent
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.getBitmapInputStream
|
import bou.amine.apps.readerforselfossv2.android.utils.glide.getBitmapInputStream
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.openInBrowserAsNewTask
|
import bou.amine.apps.readerforselfossv2.android.utils.openInBrowserAsNewTask
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.openItemUrlInternalBrowser
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.shareLink
|
import bou.amine.apps.readerforselfossv2.android.utils.shareLink
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
@ -57,10 +61,10 @@ import java.net.URL
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
|
|
||||||
|
|
||||||
class ArticleFragment : Fragment(), DIAware {
|
class ArticleFragment : Fragment(), DIAware {
|
||||||
private var fontSize: Int = 16
|
private var fontSize: Int = 16
|
||||||
private lateinit var item: SelfossModel.Item
|
private lateinit var item: SelfossModel.Item
|
||||||
|
private var mCustomTabActivityHelper: CustomTabActivityHelper? = null
|
||||||
private lateinit var url: String
|
private lateinit var url: String
|
||||||
private lateinit var contentText: String
|
private lateinit var contentText: String
|
||||||
private lateinit var contentSource: String
|
private lateinit var contentSource: String
|
||||||
@ -68,6 +72,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
private lateinit var contentTitle: String
|
private lateinit var contentTitle: String
|
||||||
private lateinit var allImages : ArrayList<String>
|
private lateinit var allImages : ArrayList<String>
|
||||||
private lateinit var fab: FloatingActionButton
|
private lateinit var fab: FloatingActionButton
|
||||||
|
private lateinit var appColors: AppColors
|
||||||
private lateinit var textAlignment: String
|
private lateinit var textAlignment: String
|
||||||
private var _binding: FragmentArticleBinding? = null
|
private var _binding: FragmentArticleBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
@ -81,7 +86,16 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
private var font = ""
|
private var font = ""
|
||||||
private var staticBar = false
|
private var staticBar = false
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
if (mCustomTabActivityHelper != null) {
|
||||||
|
mCustomTabActivityHelper!!.unbindCustomTabsService(activity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
appColors = AppColors(requireActivity())
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
val pi: ParecelableItem = requireArguments().getParcelable(ARG_ITEMS)!!
|
val pi: ParecelableItem = requireArguments().getParcelable(ARG_ITEMS)!!
|
||||||
@ -122,19 +136,25 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
|
|
||||||
fab = binding.fab
|
fab = binding.fab
|
||||||
|
|
||||||
fab.backgroundTintList = ColorStateList.valueOf(resources.getColor(R.color.colorAccent))
|
fab.backgroundTintList = ColorStateList.valueOf(appColors.colorAccent)
|
||||||
|
|
||||||
fab.rippleColor = resources.getColor(R.color.colorAccentDark)
|
fab.rippleColor = appColors.colorAccentDark
|
||||||
|
|
||||||
val floatingToolbar: FloatingToolbar = binding.floatingToolbar
|
val floatingToolbar: FloatingToolbar = binding.floatingToolbar
|
||||||
floatingToolbar.attachFab(fab)
|
floatingToolbar.attachFab(fab)
|
||||||
|
|
||||||
floatingToolbar.background = ColorDrawable(resources.getColor(R.color.colorAccent))
|
floatingToolbar.background = ColorDrawable(appColors.colorAccent)
|
||||||
|
|
||||||
|
val customTabsIntent = requireActivity().buildCustomTabsIntent()
|
||||||
|
mCustomTabActivityHelper = CustomTabActivityHelper()
|
||||||
|
mCustomTabActivityHelper!!.bindCustomTabsService(activity)
|
||||||
|
|
||||||
|
|
||||||
floatingToolbar.setClickListener(
|
floatingToolbar.setClickListener(
|
||||||
object : FloatingToolbar.ItemClickListener {
|
object : FloatingToolbar.ItemClickListener {
|
||||||
override fun onItemClick(item: MenuItem) {
|
override fun onItemClick(item: MenuItem) {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
|
R.id.more_action -> getContentFromMercury(customTabsIntent)
|
||||||
R.id.share_action -> requireActivity().shareLink(url, contentTitle)
|
R.id.share_action -> requireActivity().shareLink(url, contentTitle)
|
||||||
R.id.open_action -> requireActivity().openInBrowserAsNewTask(this@ArticleFragment.item)
|
R.id.open_action -> requireActivity().openInBrowserAsNewTask(this@ArticleFragment.item)
|
||||||
R.id.unread_action -> if (context != null) {
|
R.id.unread_action -> if (context != null) {
|
||||||
@ -180,7 +200,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (contentText.isEmptyOrNullOrNullString()) {
|
if (contentText.isEmptyOrNullOrNullString()) {
|
||||||
getContentFromMercury()
|
getContentFromMercury(customTabsIntent)
|
||||||
} else {
|
} else {
|
||||||
binding.titleView.text = contentTitle
|
binding.titleView.text = contentTitle
|
||||||
if (typeface != null) {
|
if (typeface != null) {
|
||||||
@ -246,7 +266,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getContentFromMercury() {
|
private fun getContentFromMercury(customTabsIntent: CustomTabsIntent) {
|
||||||
if (repository.isNetworkAvailable()) {
|
if (repository.isNetworkAvailable()) {
|
||||||
binding.progressBar.visibility = View.VISIBLE
|
binding.progressBar.visibility = View.VISIBLE
|
||||||
// TODO: The api should be accessed through the repository
|
// TODO: The api should be accessed through the repository
|
||||||
@ -314,7 +334,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
openInBrowserAfterFailing()
|
openInBrowserAfterFailing(customTabsIntent)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
}
|
}
|
||||||
@ -329,13 +349,14 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
override fun onFailure(
|
override fun onFailure(
|
||||||
call: Call<ParsedContent>,
|
call: Call<ParsedContent>,
|
||||||
t: Throwable
|
t: Throwable
|
||||||
) = openInBrowserAfterFailing()
|
) = openInBrowserAfterFailing(customTabsIntent)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun htmlToWebview() {
|
private fun htmlToWebview() {
|
||||||
|
val stringColor = String.format("#%06X", 0xFFFFFF and appColors.colorAccent)
|
||||||
|
|
||||||
val attrs: IntArray = intArrayOf(android.R.attr.fontFamily)
|
val attrs: IntArray = intArrayOf(android.R.attr.fontFamily)
|
||||||
val a: TypedArray = requireContext().obtainStyledAttributes(resId, attrs)
|
val a: TypedArray = requireContext().obtainStyledAttributes(resId, attrs)
|
||||||
@ -344,11 +365,12 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
binding.webcontent.settings.standardFontFamily = a.getString(0)
|
binding.webcontent.settings.standardFontFamily = a.getString(0)
|
||||||
binding.webcontent.visibility = View.VISIBLE
|
binding.webcontent.visibility = View.VISIBLE
|
||||||
|
|
||||||
val colorOnSurface = TypedValue()
|
// TODO: Set the color strings programmatically
|
||||||
requireContext().theme.resolveAttribute(R.attr.colorOnSurface, colorOnSurface, true)
|
val (stringTextColor, stringBackgroundColor) = if (appColors.isDarkTheme) {
|
||||||
|
Pair("#FFFFFF", "#303030")
|
||||||
val colorSurface = TypedValue()
|
} else {
|
||||||
requireContext().theme.resolveAttribute(R.attr.colorSurface, colorSurface, true)
|
Pair("#212121", "#FAFAFA")
|
||||||
|
}
|
||||||
|
|
||||||
binding.webcontent.settings.useWideViewPort = true
|
binding.webcontent.settings.useWideViewPort = true
|
||||||
binding.webcontent.settings.loadWithOverviewMode = true
|
binding.webcontent.settings.loadWithOverviewMode = true
|
||||||
@ -437,10 +459,10 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
| max-width: 100%;
|
| max-width: 100%;
|
||||||
| }
|
| }
|
||||||
| a {
|
| a {
|
||||||
| color: ${String.format("#%06X", 0xFFFFFF and resources.getColor(R.color.colorAccent))} !important;
|
| color: $stringColor !important;
|
||||||
| }
|
| }
|
||||||
| *:not(a) {
|
| *:not(a) {
|
||||||
| color: ${String.format("#%06X", 0xFFFFFF and colorOnSurface.data)};
|
| color: $stringTextColor;
|
||||||
| }
|
| }
|
||||||
| * {
|
| * {
|
||||||
| font-size: ${fontSize}px;
|
| font-size: ${fontSize}px;
|
||||||
@ -448,11 +470,11 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
| word-break: break-word;
|
| word-break: break-word;
|
||||||
| overflow:hidden;
|
| overflow:hidden;
|
||||||
| line-height: 1.5em;
|
| line-height: 1.5em;
|
||||||
| background-color: ${String.format("#%06X", 0xFFFFFF and colorSurface.data)};
|
| background-color: $stringBackgroundColor;
|
||||||
| }
|
| }
|
||||||
| body, html {
|
| body, html {
|
||||||
| background-color: ${String.format("#%06X", 0xFFFFFF and colorSurface.data)} !important;
|
| background-color: $stringBackgroundColor !important;
|
||||||
| border-color: ${String.format("#%06X", 0xFFFFFF and colorSurface.data)} !important;
|
| border-color: $stringBackgroundColor !important;
|
||||||
| padding: 0 !important;
|
| padding: 0 !important;
|
||||||
| margin: 0 !important;
|
| margin: 0 !important;
|
||||||
| }
|
| }
|
||||||
@ -462,7 +484,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
| pre, code {
|
| pre, code {
|
||||||
| white-space: pre-wrap;
|
| white-space: pre-wrap;
|
||||||
| width:100%;
|
| width:100%;
|
||||||
| background-color: ${String.format("#%06X", 0xFFFFFF and colorSurface.data)};
|
| background-color: $stringBackgroundColor;
|
||||||
| }
|
| }
|
||||||
| </style>
|
| </style>
|
||||||
| $fontLinkAndStyle
|
| $fontLinkAndStyle
|
||||||
@ -486,9 +508,13 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
binding.nestedScrollView.smoothScrollBy(0, -height/2)
|
binding.nestedScrollView.smoothScrollBy(0, -height/2)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openInBrowserAfterFailing() {
|
private fun openInBrowserAfterFailing(customTabsIntent: CustomTabsIntent) {
|
||||||
binding.progressBar.visibility = View.GONE
|
binding.progressBar.visibility = View.GONE
|
||||||
requireActivity().openInBrowserAsNewTask(this@ArticleFragment.item)
|
requireActivity().openItemUrlInternalBrowser(
|
||||||
|
url,
|
||||||
|
customTabsIntent,
|
||||||
|
requireActivity()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -7,16 +7,22 @@ import android.text.Editable
|
|||||||
import android.text.InputFilter
|
import android.text.InputFilter
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
import bou.amine.apps.readerforselfossv2.android.R
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBinding
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.Toppings
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
|
import com.ftinc.scoop.Scoop
|
||||||
|
|
||||||
private const val TITLE_TAG = "settingsActivityTitle"
|
private const val TITLE_TAG = "settingsActivityTitle"
|
||||||
|
|
||||||
@ -25,8 +31,15 @@ class SettingsActivity : AppCompatActivity(),
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("dark_theme", false)) {
|
||||||
|
setTheme(R.style.NoBarDark)
|
||||||
|
}
|
||||||
val binding = ActivitySettingsBinding.inflate(layoutInflater)
|
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)
|
setContentView(binding.root)
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
supportFragmentManager
|
supportFragmentManager
|
||||||
@ -156,11 +169,21 @@ class SettingsActivity : AppCompatActivity(),
|
|||||||
class ThemePreferenceFragment : PreferenceFragmentCompat() {
|
class ThemePreferenceFragment : PreferenceFragmentCompat() {
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.pref_theme, rootKey)
|
setPreferencesFromResource(R.xml.pref_theme, rootKey)
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
}
|
||||||
|
|
||||||
preferenceManager.findPreference<Preference>("currentMode")?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
AppCompatDelegate.setDefaultNightMode(newValue.toString().toInt()) // ListPreference Only takes string-arrays ¯\_(ツ)_/¯
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
true
|
inflater.inflate(R.menu.settings_theme, menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
val id = item.itemId
|
||||||
|
if (id == R.id.clear) {
|
||||||
|
AppColors.resetColors()
|
||||||
|
requireActivity().recreate()
|
||||||
}
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
package bou.amine.apps.readerforselfossv2.android.themes
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
|
import com.russhwolf.settings.Settings
|
||||||
|
|
||||||
|
class AppColors(a: Activity) {
|
||||||
|
|
||||||
|
@ColorInt val colorPrimary: Int
|
||||||
|
@ColorInt val colorPrimaryDark: Int
|
||||||
|
@ColorInt val colorAccent: Int
|
||||||
|
@ColorInt val colorAccentDark: Int
|
||||||
|
@ColorInt val colorBackground: Int
|
||||||
|
@ColorInt val textColor: Int
|
||||||
|
val isDarkTheme: Boolean
|
||||||
|
|
||||||
|
init {
|
||||||
|
val settings = Settings()
|
||||||
|
|
||||||
|
colorPrimary =
|
||||||
|
settings.getInt(
|
||||||
|
"color_primary",
|
||||||
|
a.resources.getColor(R.color.colorPrimary)
|
||||||
|
)
|
||||||
|
colorPrimaryDark =
|
||||||
|
settings.getInt(
|
||||||
|
"color_primary_dark",
|
||||||
|
a.resources.getColor(R.color.colorPrimaryDark)
|
||||||
|
)
|
||||||
|
colorAccent =
|
||||||
|
settings.getInt(
|
||||||
|
"color_accent",
|
||||||
|
a.resources.getColor(R.color.colorAccent)
|
||||||
|
)
|
||||||
|
colorAccentDark =
|
||||||
|
settings.getInt(
|
||||||
|
"color_accent_dark",
|
||||||
|
a.resources.getColor(R.color.colorAccentDark)
|
||||||
|
)
|
||||||
|
isDarkTheme =
|
||||||
|
settings.getBoolean(
|
||||||
|
"dark_theme",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
colorBackground = if (isDarkTheme) {
|
||||||
|
a.setTheme(R.style.NoBarDark)
|
||||||
|
a.resources.getColor(R.color.darkBackground)
|
||||||
|
} else {
|
||||||
|
a.setTheme(R.style.NoBar)
|
||||||
|
a.resources.getColor(R.color.grey_50)
|
||||||
|
}
|
||||||
|
|
||||||
|
textColor = if (isDarkTheme) {
|
||||||
|
a.resources.getColor(R.color.white)
|
||||||
|
} else {
|
||||||
|
a.resources.getColor(R.color.grey_900)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun resetColors() {
|
||||||
|
val settings = Settings()
|
||||||
|
settings.remove("color_primary")
|
||||||
|
settings.remove("color_primary_dark")
|
||||||
|
settings.remove("color_accent")
|
||||||
|
settings.remove("color_accent_dark")
|
||||||
|
settings.remove("dark_theme")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package bou.amine.apps.readerforselfossv2.android.themes
|
||||||
|
|
||||||
|
enum class Toppings(val value: Int) {
|
||||||
|
PRIMARY(1),
|
||||||
|
PRIMARY_DARK(2),
|
||||||
|
ACCENT(3),
|
||||||
|
ACCENT_DARK(4)
|
||||||
|
}
|
@ -15,16 +15,109 @@ import android.view.MotionEvent
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.browser.customtabs.CustomTabsIntent
|
||||||
import bou.amine.apps.readerforselfossv2.android.R
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
import bou.amine.apps.readerforselfossv2.android.ReaderActivity
|
import bou.amine.apps.readerforselfossv2.android.ReaderActivity
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.utils.toStringUriWithHttp
|
import bou.amine.apps.readerforselfossv2.utils.toStringUriWithHttp
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
|
|
||||||
|
fun Context.buildCustomTabsIntent(): CustomTabsIntent {
|
||||||
|
|
||||||
|
val actionIntent = Intent(Intent.ACTION_SEND)
|
||||||
|
actionIntent.type = "text/plain"
|
||||||
|
val pflags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
PendingIntent.FLAG_IMMUTABLE
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
val createPendingShareIntent: PendingIntent = PendingIntent.getActivity(
|
||||||
|
this,
|
||||||
|
0,
|
||||||
|
actionIntent,
|
||||||
|
pflags
|
||||||
|
)
|
||||||
|
|
||||||
|
val intentBuilder = CustomTabsIntent.Builder()
|
||||||
|
|
||||||
|
// TODO: change to primary when it's possible to customize custom tabs title color
|
||||||
|
//intentBuilder.setToolbarColor(c.getResources().getColor(R.color.colorPrimary));
|
||||||
|
intentBuilder.setToolbarColor(resources.getColor(R.color.colorAccentDark))
|
||||||
|
intentBuilder.setShowTitle(true)
|
||||||
|
|
||||||
|
|
||||||
|
intentBuilder.setStartAnimations(
|
||||||
|
this,
|
||||||
|
R.anim.slide_in_right,
|
||||||
|
R.anim.slide_out_left
|
||||||
|
)
|
||||||
|
intentBuilder.setExitAnimations(
|
||||||
|
this,
|
||||||
|
android.R.anim.slide_in_left,
|
||||||
|
android.R.anim.slide_out_right
|
||||||
|
)
|
||||||
|
|
||||||
|
val closeicon = BitmapFactory.decodeResource(resources, R.drawable.ic_close_white_24dp)
|
||||||
|
intentBuilder.setCloseButtonIcon(closeicon)
|
||||||
|
|
||||||
|
val shareLabel = this.getString(R.string.label_share)
|
||||||
|
val icon = BitmapFactory.decodeResource(
|
||||||
|
resources,
|
||||||
|
R.drawable.ic_share_white_24dp
|
||||||
|
)
|
||||||
|
intentBuilder.setActionButton(icon, shareLabel, createPendingShareIntent)
|
||||||
|
|
||||||
|
return intentBuilder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.openItemUrlInternally(
|
||||||
|
allItems: ArrayList<SelfossModel.Item>,
|
||||||
|
currentItem: Int,
|
||||||
|
linkDecoded: String,
|
||||||
|
customTabsIntent: CustomTabsIntent,
|
||||||
|
articleViewer: Boolean,
|
||||||
|
app: Activity
|
||||||
|
) {
|
||||||
|
if (articleViewer) {
|
||||||
|
ReaderActivity.allItems = allItems
|
||||||
|
val intent = Intent(this, ReaderActivity::class.java)
|
||||||
|
intent.putExtra("currentItem", currentItem)
|
||||||
|
app.startActivity(intent)
|
||||||
|
} else {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Context.openItemUrl(
|
fun Context.openItemUrl(
|
||||||
allItems: ArrayList<SelfossModel.Item>,
|
allItems: ArrayList<SelfossModel.Item>,
|
||||||
currentItem: Int,
|
currentItem: Int,
|
||||||
linkDecoded: String,
|
linkDecoded: String,
|
||||||
|
customTabsIntent: CustomTabsIntent,
|
||||||
|
internalBrowser: Boolean,
|
||||||
articleViewer: Boolean,
|
articleViewer: Boolean,
|
||||||
app: Activity
|
app: Activity
|
||||||
) {
|
) {
|
||||||
@ -36,24 +129,41 @@ fun Context.openItemUrl(
|
|||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
} else {
|
} else {
|
||||||
if (articleViewer) {
|
if (!internalBrowser) {
|
||||||
ReaderActivity.allItems = allItems
|
openInBrowser(linkDecoded, app)
|
||||||
val intent = Intent(this, ReaderActivity::class.java)
|
} else if (articleViewer) {
|
||||||
intent.putExtra("currentItem", currentItem)
|
this.openItemUrlInternally(
|
||||||
app.startActivity(intent)
|
allItems,
|
||||||
|
currentItem,
|
||||||
|
linkDecoded,
|
||||||
|
customTabsIntent,
|
||||||
|
articleViewer,
|
||||||
|
app
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
val intent = Intent(Intent.ACTION_VIEW)
|
this.openItemUrlInternalBrowser(
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
linkDecoded,
|
||||||
intent.data = Uri.parse(linkDecoded.toStringUriWithHttp())
|
customTabsIntent,
|
||||||
startActivity(intent)
|
app
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun openInBrowser(linkDecoded: String, app: Activity) {
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
|
intent.data = Uri.parse(linkDecoded)
|
||||||
|
try {
|
||||||
|
app.startActivity(intent)
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
Toast.makeText(app.baseContext, e.message, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun String.isUrlValid(): Boolean =
|
fun String.isUrlValid(): Boolean =
|
||||||
this.toHttpUrlOrNull() != null && Patterns.WEB_URL.matcher(this).matches()
|
this.toHttpUrlOrNull() != null && Patterns.WEB_URL.matcher(this).matches()
|
||||||
|
|
||||||
fun String.isBaseUrlInvalid(): Boolean {
|
fun String.isBaseUrlInvalid(ctx: Context): Boolean {
|
||||||
val baseUrl = this.toHttpUrlOrNull()
|
val baseUrl = this.toHttpUrlOrNull()
|
||||||
var existsAndEndsWithSlash = false
|
var existsAndEndsWithSlash = false
|
||||||
if (baseUrl != null) {
|
if (baseUrl != null) {
|
||||||
@ -71,7 +181,7 @@ fun Context.openInBrowserAsNewTask(i: SelfossModel.Item) {
|
|||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
class LinkOnTouchListener : View.OnTouchListener {
|
class LinkOnTouchListener: View.OnTouchListener {
|
||||||
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
|
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
|
||||||
var ret = false
|
var ret = false
|
||||||
val widget: TextView = v as TextView
|
val widget: TextView = v as TextView
|
||||||
@ -81,8 +191,7 @@ class LinkOnTouchListener : View.OnTouchListener {
|
|||||||
val action = event!!.action
|
val action = event!!.action
|
||||||
|
|
||||||
if (action == MotionEvent.ACTION_UP ||
|
if (action == MotionEvent.ACTION_UP ||
|
||||||
action == MotionEvent.ACTION_DOWN
|
action == MotionEvent.ACTION_DOWN) {
|
||||||
) {
|
|
||||||
var x: Float = event.x
|
var x: Float = event.x
|
||||||
var y: Float = event.y
|
var y: Float = event.y
|
||||||
|
|
||||||
|
@ -0,0 +1,153 @@
|
|||||||
|
package bou.amine.apps.readerforselfossv2.android.utils.customtabs;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import androidx.browser.customtabs.CustomTabsClient;
|
||||||
|
import androidx.browser.customtabs.CustomTabsIntent;
|
||||||
|
import androidx.browser.customtabs.CustomTabsServiceConnection;
|
||||||
|
import androidx.browser.customtabs.CustomTabsSession;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a helper class to manage the connection to the Custom Tabs Service.
|
||||||
|
*/
|
||||||
|
public class CustomTabActivityHelper implements ServiceConnectionCallback {
|
||||||
|
private CustomTabsSession mCustomTabsSession;
|
||||||
|
private CustomTabsClient mClient;
|
||||||
|
private CustomTabsServiceConnection mConnection;
|
||||||
|
private ConnectionCallback mConnectionCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the URL on a Custom Tab if possible. Otherwise fallsback to opening it on a WebView.
|
||||||
|
*
|
||||||
|
* @param activity The host activity.
|
||||||
|
* @param customTabsIntent a CustomTabsIntent to be used if Custom Tabs is available.
|
||||||
|
* @param uri the Uri to be opened.
|
||||||
|
* @param fallback a CustomTabFallback to be used if Custom Tabs is not available.
|
||||||
|
*/
|
||||||
|
public static void openCustomTab(Activity activity,
|
||||||
|
CustomTabsIntent customTabsIntent,
|
||||||
|
Uri uri,
|
||||||
|
CustomTabFallback fallback) {
|
||||||
|
String packageName = CustomTabsHelper.getPackageNameToUse(activity);
|
||||||
|
|
||||||
|
//If we cant find a package name, it means theres no browser that supports
|
||||||
|
//Chrome Custom Tabs installed. So, we fallback to the webview
|
||||||
|
if (packageName == null) {
|
||||||
|
if (fallback != null) {
|
||||||
|
fallback.openUri(activity, uri);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
customTabsIntent.intent.setPackage(packageName);
|
||||||
|
customTabsIntent.launchUrl(activity, uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbinds the Activity from the Custom Tabs Service.
|
||||||
|
*
|
||||||
|
* @param activity the activity that is connected to the service.
|
||||||
|
*/
|
||||||
|
public void unbindCustomTabsService(Activity activity) {
|
||||||
|
if (mConnection == null) return;
|
||||||
|
activity.unbindService(mConnection);
|
||||||
|
mClient = null;
|
||||||
|
mCustomTabsSession = null;
|
||||||
|
mConnection = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates or retrieves an exiting CustomTabsSession.
|
||||||
|
*
|
||||||
|
* @return a CustomTabsSession.
|
||||||
|
*/
|
||||||
|
public CustomTabsSession getSession() {
|
||||||
|
if (mClient == null) {
|
||||||
|
mCustomTabsSession = null;
|
||||||
|
} else if (mCustomTabsSession == null) {
|
||||||
|
mCustomTabsSession = mClient.newSession(null);
|
||||||
|
}
|
||||||
|
return mCustomTabsSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a Callback to be called when connected or disconnected from the Custom Tabs Service.
|
||||||
|
*
|
||||||
|
* @param connectionCallback
|
||||||
|
*/
|
||||||
|
public void setConnectionCallback(ConnectionCallback connectionCallback) {
|
||||||
|
this.mConnectionCallback = connectionCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds the Activity to the Custom Tabs Service.
|
||||||
|
*
|
||||||
|
* @param activity the activity to be binded to the service.
|
||||||
|
*/
|
||||||
|
public void bindCustomTabsService(Activity activity) {
|
||||||
|
if (mClient != null) return;
|
||||||
|
|
||||||
|
String packageName = CustomTabsHelper.getPackageNameToUse(activity);
|
||||||
|
if (packageName == null) return;
|
||||||
|
|
||||||
|
mConnection = new ServiceConnection(this);
|
||||||
|
CustomTabsClient.bindCustomTabsService(activity, packageName, mConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if call to mayLaunchUrl was accepted.
|
||||||
|
* @see {@link CustomTabsSession#mayLaunchUrl(Uri, Bundle, List)}.
|
||||||
|
*/
|
||||||
|
public boolean mayLaunchUrl(Uri uri, Bundle extras, List<Bundle> otherLikelyBundles) {
|
||||||
|
if (mClient == null) return false;
|
||||||
|
|
||||||
|
CustomTabsSession session = getSession();
|
||||||
|
return session != null && session.mayLaunchUrl(uri, extras, otherLikelyBundles);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(CustomTabsClient client) {
|
||||||
|
mClient = client;
|
||||||
|
mClient.warmup(0L);
|
||||||
|
if (mConnectionCallback != null) mConnectionCallback.onCustomTabsConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected() {
|
||||||
|
mClient = null;
|
||||||
|
mCustomTabsSession = null;
|
||||||
|
if (mConnectionCallback != null) mConnectionCallback.onCustomTabsDisconnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Callback for when the service is connected or disconnected. Use those callbacks to
|
||||||
|
* handle UI changes when the service is connected or disconnected.
|
||||||
|
*/
|
||||||
|
public interface ConnectionCallback {
|
||||||
|
/**
|
||||||
|
* Called when the service is connected.
|
||||||
|
*/
|
||||||
|
void onCustomTabsConnected();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the service is disconnected.
|
||||||
|
*/
|
||||||
|
void onCustomTabsDisconnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be used as a fallback to open the Uri when Custom Tabs is not available.
|
||||||
|
*/
|
||||||
|
public interface CustomTabFallback {
|
||||||
|
/**
|
||||||
|
* @param activity The Activity that wants to open the Uri.
|
||||||
|
* @param uri The uri to be opened by the fallback.
|
||||||
|
*/
|
||||||
|
void openUri(Activity activity, Uri uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,129 @@
|
|||||||
|
package bou.amine.apps.readerforselfossv2.android.utils.customtabs;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import androidx.browser.customtabs.CustomTabsService;
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.customtabs.helpers.KeepAliveService;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@SuppressWarnings("ALL")
|
||||||
|
class CustomTabsHelper {
|
||||||
|
private static final String TAG = "CustomTabsHelper";
|
||||||
|
private static final String STABLE_PACKAGE = "com.android.chrome";
|
||||||
|
private static final String BETA_PACKAGE = "com.chrome.beta";
|
||||||
|
private static final String DEV_PACKAGE = "com.chrome.dev";
|
||||||
|
private static final String LOCAL_PACKAGE = "com.google.android.apps.chrome";
|
||||||
|
private static final String EXTRA_CUSTOM_TABS_KEEP_ALIVE =
|
||||||
|
"android.support.customtabs.extra.KEEP_ALIVE";
|
||||||
|
|
||||||
|
private static String sPackageNameToUse;
|
||||||
|
|
||||||
|
private CustomTabsHelper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addKeepAliveExtra(Context context, Intent intent) {
|
||||||
|
Intent keepAliveIntent = new Intent().setClassName(
|
||||||
|
context.getPackageName(), KeepAliveService.class.getCanonicalName());
|
||||||
|
intent.putExtra(EXTRA_CUSTOM_TABS_KEEP_ALIVE, keepAliveIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Goes through all apps that handle VIEW intents and have a warmup service. Picks
|
||||||
|
* the one chosen by the user if there is one, otherwise makes a best effort to return a
|
||||||
|
* valid package name.
|
||||||
|
* <p>
|
||||||
|
* This is <strong>not</strong> threadsafe.
|
||||||
|
*
|
||||||
|
* @param context {@link Context} to use for accessing {@link PackageManager}.
|
||||||
|
* @return The package name recommended to use for connecting to custom tabs related components.
|
||||||
|
*/
|
||||||
|
public static String getPackageNameToUse(Context context) {
|
||||||
|
if (sPackageNameToUse != null) return sPackageNameToUse;
|
||||||
|
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
// Get default VIEW intent handler.
|
||||||
|
Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
|
||||||
|
ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0);
|
||||||
|
String defaultViewHandlerPackageName = null;
|
||||||
|
if (defaultViewHandlerInfo != null) {
|
||||||
|
defaultViewHandlerPackageName = defaultViewHandlerInfo.activityInfo.packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all apps that can handle VIEW intents.
|
||||||
|
List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
|
||||||
|
List<String> packagesSupportingCustomTabs = new ArrayList<>();
|
||||||
|
for (ResolveInfo info : resolvedActivityList) {
|
||||||
|
Intent serviceIntent = new Intent();
|
||||||
|
serviceIntent.setAction(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION);
|
||||||
|
serviceIntent.setPackage(info.activityInfo.packageName);
|
||||||
|
if (pm.resolveService(serviceIntent, 0) != null) {
|
||||||
|
packagesSupportingCustomTabs.add(info.activityInfo.packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now packagesSupportingCustomTabs contains all apps that can handle both VIEW intents
|
||||||
|
// and service calls.
|
||||||
|
if (packagesSupportingCustomTabs.isEmpty()) {
|
||||||
|
sPackageNameToUse = null;
|
||||||
|
} else if (packagesSupportingCustomTabs.size() == 1) {
|
||||||
|
sPackageNameToUse = packagesSupportingCustomTabs.get(0);
|
||||||
|
} else if (!TextUtils.isEmpty(defaultViewHandlerPackageName)
|
||||||
|
&& !hasSpecializedHandlerIntents(context, activityIntent)
|
||||||
|
&& packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)) {
|
||||||
|
sPackageNameToUse = defaultViewHandlerPackageName;
|
||||||
|
} else if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) {
|
||||||
|
sPackageNameToUse = STABLE_PACKAGE;
|
||||||
|
} else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) {
|
||||||
|
sPackageNameToUse = BETA_PACKAGE;
|
||||||
|
} else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) {
|
||||||
|
sPackageNameToUse = DEV_PACKAGE;
|
||||||
|
} else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) {
|
||||||
|
sPackageNameToUse = LOCAL_PACKAGE;
|
||||||
|
}
|
||||||
|
return sPackageNameToUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to check whether there is a specialized handler for a given intent.
|
||||||
|
*
|
||||||
|
* @param intent The intent to check with.
|
||||||
|
* @return Whether there is a specialized handler for the given intent.
|
||||||
|
*/
|
||||||
|
private static boolean hasSpecializedHandlerIntents(Context context, Intent intent) {
|
||||||
|
try {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
List<ResolveInfo> handlers = pm.queryIntentActivities(
|
||||||
|
intent,
|
||||||
|
PackageManager.GET_RESOLVED_FILTER);
|
||||||
|
if (handlers == null || handlers.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (ResolveInfo resolveInfo : handlers) {
|
||||||
|
IntentFilter filter = resolveInfo.filter;
|
||||||
|
if (filter == null) continue;
|
||||||
|
if (filter.countDataAuthorities() == 0 || filter.countDataPaths() == 0) continue;
|
||||||
|
if (resolveInfo.activityInfo == null) continue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Log.e(TAG, "Runtime exception while getting specialized handlers");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return All possible chrome package names that provide custom tabs feature.
|
||||||
|
*/
|
||||||
|
public static String[] getPackages() {
|
||||||
|
return new String[]{"", STABLE_PACKAGE, BETA_PACKAGE, DEV_PACKAGE, LOCAL_PACKAGE};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package bou.amine.apps.readerforselfossv2.android.utils.customtabs;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import androidx.browser.customtabs.CustomTabsClient;
|
||||||
|
import androidx.browser.customtabs.CustomTabsServiceConnection;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation for the CustomTabsServiceConnection that avoids leaking the
|
||||||
|
* ServiceConnectionCallback
|
||||||
|
*/
|
||||||
|
public class ServiceConnection extends CustomTabsServiceConnection {
|
||||||
|
// A weak reference to the ServiceConnectionCallback to avoid leaking it.
|
||||||
|
private WeakReference<ServiceConnectionCallback> mConnectionCallback;
|
||||||
|
|
||||||
|
public ServiceConnection(ServiceConnectionCallback connectionCallback) {
|
||||||
|
mConnectionCallback = new WeakReference<>(connectionCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
|
||||||
|
ServiceConnectionCallback connectionCallback = mConnectionCallback.get();
|
||||||
|
if (connectionCallback != null) connectionCallback.onServiceConnected(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
ServiceConnectionCallback connectionCallback = mConnectionCallback.get();
|
||||||
|
if (connectionCallback != null) connectionCallback.onServiceDisconnected();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package bou.amine.apps.readerforselfossv2.android.utils.customtabs;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.browser.customtabs.CustomTabsClient;
|
||||||
|
|
||||||
|
|
||||||
|
public interface ServiceConnectionCallback {
|
||||||
|
/**
|
||||||
|
* Called when the service is connected.
|
||||||
|
*
|
||||||
|
* @param client a CustomTabsClient
|
||||||
|
*/
|
||||||
|
void onServiceConnected(CustomTabsClient client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the service is disconnected.
|
||||||
|
*/
|
||||||
|
void onServiceDisconnected();
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package bou.amine.apps.readerforselfossv2.android.utils.customtabs.helpers;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
public class KeepAliveService extends Service {
|
||||||
|
private static final Binder sBinder = new Binder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return sBinder;
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<item>
|
<item
|
||||||
<shape android:shape="rectangle" >
|
android:drawable="@color/ic_launcher_background"/>
|
||||||
<solid android:color="?attr/colorSurface" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<bitmap
|
<bitmap
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M13,12h7v1.5h-7zM13,9.5h7L20,11h-7zM13,14.5h7L20,16h-7zM21,4L3,4c-1.1,0 -2,0.9 -2,2v13c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2L23,6c0,-1.1 -0.9,-2 -2,-2zM21,19h-9L12,6h9v13z"/>
|
||||||
|
</vector>
|
@ -14,12 +14,12 @@
|
|||||||
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"
|
||||||
|
app:theme="@style/ToolBarStyle"
|
||||||
/>
|
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
@ -107,7 +107,8 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@+id/tags"
|
app:layout_constraintTop_toBottomOf="@+id/tags"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
android:layout_height="40dp"/>
|
android:layout_height="40dp"
|
||||||
|
android:theme="@style/App.Spinner"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:text="@string/add_source_save"
|
android:text="@string/add_source_save"
|
||||||
@ -115,7 +116,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/saveBtn"
|
android:id="@+id/saveBtn"
|
||||||
android:elevation="5dp"
|
android:elevation="5dp"
|
||||||
android:textColor="?android:textColorPrimary"
|
android:textColor="?attr/colorAccent"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
|
@ -28,12 +28,12 @@
|
|||||||
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"
|
||||||
|
app:theme="@style/ToolBarStyle"
|
||||||
/>
|
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
@ -78,12 +78,10 @@
|
|||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
<com.ashokvarma.bottomnavigation.BottomNavigationBar
|
<com.ashokvarma.bottomnavigation.BottomNavigationBar
|
||||||
|
android:layout_gravity="bottom"
|
||||||
android:id="@+id/bottomBar"
|
android:id="@+id/bottomBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"/>
|
||||||
android:layout_gravity="bottom"
|
|
||||||
app:bnbActiveColor="@color/colorAccent"
|
|
||||||
app:bnbBackgroundColor="?attr/bottomBarBackground" />
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
<com.mikepenz.materialdrawer.widget.MaterialDrawerSliderView
|
<com.mikepenz.materialdrawer.widget.MaterialDrawerSliderView
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
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"
|
||||||
|
app:popupTheme="?attr/toolbarPopupTheme"
|
||||||
/>
|
app:theme="@style/ToolBarStyle" />
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
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"
|
||||||
|
app:theme="@style/ToolBarStyle"
|
||||||
/>
|
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
@ -17,10 +17,8 @@
|
|||||||
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"
|
app:popupTheme="?attr/toolbarPopupTheme"
|
||||||
|
app:theme="@style/ToolBarStyle" />
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<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"
|
|
||||||
android:id="@+id/layout"
|
android:id="@+id/layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@ -9,11 +8,11 @@
|
|||||||
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" />
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
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"
|
||||||
|
app:theme="@style/ToolBarStyle"
|
||||||
/>
|
app:popupTheme="?attr/toolbarPopupTheme" />
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
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"
|
||||||
card_view:layout_constraintBottom_toBottomOf="parent">
|
card_view:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:cardBackgroundColor="?cardBackgroundColor">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:paddingBottom="48dp"
|
android:paddingBottom="48dp"
|
||||||
android:background="?attr/webviewBackground"
|
android:background="?android:colorBackground"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
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"
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
android:title="@string/unmark"
|
android:title="@string/unmark"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/more_action"
|
||||||
|
android:icon="@drawable/ic_chrome_reader_mode_white_24dp"
|
||||||
|
android:title="@string/reader_action_more"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/open_action"
|
android:id="@+id/open_action"
|
||||||
android:icon="@drawable/ic_open_in_browser_white_24dp"
|
android:icon="@drawable/ic_open_in_browser_white_24dp"
|
||||||
|
10
androidApp/src/main/res/menu/settings_theme.xml
Normal file
10
androidApp/src/main/res/menu/settings_theme.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/clear"
|
||||||
|
android:icon="@drawable/ic_history_white_24dp"
|
||||||
|
android:title="@string/drawer_action_clear"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
</menu>
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Recompte d'articles no llegits"</string>
|
<string name="switch_unread_count_title">"Recompte d'articles no llegits"</string>
|
||||||
<string name="display_all_counts_title">"Recompte d'articles llegits i preferits"</string>
|
<string name="display_all_counts_title">"Recompte d'articles llegits i preferits"</string>
|
||||||
<string name="text_wrong_url">"Sembla que esteu utilitzant un URL no vàlid. Assegureu-vos que és correcte, i si el problema persisteix, poseu-vos en contacte amb mi (a través de l'enllaç de contacte que hi ha a la Botiga). Tingueu en compte que per utilitzar aquesta aplicació cal que també utilitzeu Selfoss. Si no, no podreu accedir a canals RSS."</string>
|
<string name="text_wrong_url">"Sembla que esteu utilitzant un URL no vàlid. Assegureu-vos que és correcte, i si el problema persisteix, poseu-vos en contacte amb mi (a través de l'enllaç de contacte que hi ha a la Botiga). Tingueu en compte que per utilitzar aquesta aplicació cal que també utilitzeu Selfoss. Si no, no podreu accedir a canals RSS."</string>
|
||||||
<string name="pref_article_viewer_title">"Obre els enllaços dins de l'aplicació"</string>
|
<string name="pref_general_internal_browser_title">"Obre els enllaços dins de l'aplicació"</string>
|
||||||
<string name="pref_article_viewer_on">"Els articles s'obriran dins de l'aplicació"</string>
|
<string name="pref_general_internal_browser_on">"Els articles s'obriran dins de l'aplicació"</string>
|
||||||
<string name="pref_article_viewer_off">"Els articles s'obriran amb el navegador predeterminat"</string>
|
<string name="pref_general_internal_browser_off">"Els articles s'obriran amb el navegador predeterminat"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Obre el visualitzador d'articles"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"S'obrirà el visualitzador d'articles en lloc del navegador intern"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"S'obrirà el navegador intern en lloc del visualitzador d'articles"</string>
|
||||||
<string name="pref_general_category_links">"Gestió d'enllaços"</string>
|
<string name="pref_general_category_links">"Gestió d'enllaços"</string>
|
||||||
<string name="pref_general_category_displaying">"Visualització"</string>
|
<string name="pref_general_category_displaying">"Visualització"</string>
|
||||||
<string name="pref_switch_card_view_on">"Els articles es mostraran com a targetes"</string>
|
<string name="pref_switch_card_view_on">"Els articles es mostraran com a targetes"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Zeige Anzahl ungelesener Artikel"</string>
|
<string name="switch_unread_count_title">"Zeige Anzahl ungelesener Artikel"</string>
|
||||||
<string name="display_all_counts_title">"Zeige Anzahl der Favoriten und gelesenen Artikel"</string>
|
<string name="display_all_counts_title">"Zeige Anzahl der Favoriten und gelesenen Artikel"</string>
|
||||||
<string name="text_wrong_url">"Sie scheinen eine ungültige URL verwenden. Stellen Sie sicher, dass die URL richtig ist. Sollte das Problem weiterhin bestehen kontaktieren Sie mich (über den Playstore-Kontakt-Link). Bitte beachten Sie, dass Sie Selfoss benötigen um RSS-Feeds zu lesen."</string>
|
<string name="text_wrong_url">"Sie scheinen eine ungültige URL verwenden. Stellen Sie sicher, dass die URL richtig ist. Sollte das Problem weiterhin bestehen kontaktieren Sie mich (über den Playstore-Kontakt-Link). Bitte beachten Sie, dass Sie Selfoss benötigen um RSS-Feeds zu lesen."</string>
|
||||||
<string name="pref_article_viewer_title">"Öffne Links innerhalb der App"</string>
|
<string name="pref_general_internal_browser_title">"Öffne Links innerhalb der App"</string>
|
||||||
<string name="pref_article_viewer_on">"Artikel werden innerhalb der App geöffnet"</string>
|
<string name="pref_general_internal_browser_on">"Artikel werden innerhalb der App geöffnet"</string>
|
||||||
<string name="pref_article_viewer_off">"Artikel werden mit deinem Standard-Browser geöffnet"</string>
|
<string name="pref_general_internal_browser_off">"Artikel werden mit deinem Standard-Browser geöffnet"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Verwenden Sie den Artikel-viewer"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Artikel-Viewer wird anstelle des internen Browser verwendet"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Der internen Browser wird anstelle des Artikel-Viewer verwendet"</string>
|
||||||
<string name="pref_general_category_links">"Umgang mit Links"</string>
|
<string name="pref_general_category_links">"Umgang mit Links"</string>
|
||||||
<string name="pref_general_category_displaying">"Ansicht"</string>
|
<string name="pref_general_category_displaying">"Ansicht"</string>
|
||||||
<string name="pref_switch_card_view_on">"Artikel werden als Kacheln angezeigt"</string>
|
<string name="pref_switch_card_view_on">"Artikel werden als Kacheln angezeigt"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Mostrar recuento no leído"</string>
|
<string name="switch_unread_count_title">"Mostrar recuento no leído"</string>
|
||||||
<string name="display_all_counts_title">"Mostrar recuento de favoritos y leídos"</string>
|
<string name="display_all_counts_title">"Mostrar recuento de favoritos y leídos"</string>
|
||||||
<string name="text_wrong_url">"Parece estar tratando de utilizar una dirección URL inválida. Asegúrese de que sea correcta y si el problema persiste, póngase en contacto conmigo (mediante el enlace de contacto de la tienda). Tenga en cuenta que la aplicación necesita utilizar Selfoss. No se puede acceder al contenido RSS sin él."</string>
|
<string name="text_wrong_url">"Parece estar tratando de utilizar una dirección URL inválida. Asegúrese de que sea correcta y si el problema persiste, póngase en contacto conmigo (mediante el enlace de contacto de la tienda). Tenga en cuenta que la aplicación necesita utilizar Selfoss. No se puede acceder al contenido RSS sin él."</string>
|
||||||
<string name="pref_article_viewer_title">"Abrir enlaces dentro de la aplicación"</string>
|
<string name="pref_general_internal_browser_title">"Abrir enlaces dentro de la aplicación"</string>
|
||||||
<string name="pref_article_viewer_on">"Los artículos se abrirán dentro de la aplicación"</string>
|
<string name="pref_general_internal_browser_on">"Los artículos se abrirán dentro de la aplicación"</string>
|
||||||
<string name="pref_article_viewer_off">"Los artículos se abrirán con tu navegador predeterminado"</string>
|
<string name="pref_general_internal_browser_off">"Los artículos se abrirán con tu navegador predeterminado"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Utilizar el visor de artículo"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Se usará el visor de artículos en lugar del navegador interno"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Se utilizará el navegador interno en lugar del visor de artículo"</string>
|
||||||
<string name="pref_general_category_links">"Control de enlaces"</string>
|
<string name="pref_general_category_links">"Control de enlaces"</string>
|
||||||
<string name="pref_general_category_displaying">"Mostrando"</string>
|
<string name="pref_general_category_displaying">"Mostrando"</string>
|
||||||
<string name="pref_switch_card_view_on">"Los artículos se mostrarán como tarjetas"</string>
|
<string name="pref_switch_card_view_on">"Los artículos se mostrarán como tarjetas"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Display unread count"</string>
|
<string name="switch_unread_count_title">"Display unread count"</string>
|
||||||
<string name="display_all_counts_title">"Display count for favorite and read"</string>
|
<string name="display_all_counts_title">"Display count for favorite and read"</string>
|
||||||
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
||||||
<string name="pref_article_viewer_title">"Open links inside the app"</string>
|
<string name="pref_general_internal_browser_title">"Open links inside the app"</string>
|
||||||
<string name="pref_article_viewer_on">"Articles will open inside the app"</string>
|
<string name="pref_general_internal_browser_on">"Articles will open inside the app"</string>
|
||||||
<string name="pref_article_viewer_off">"Articles will open with your default browser"</string>
|
<string name="pref_general_internal_browser_off">"Articles will open with your default browser"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Use the article viewer"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Will use the article viewer instead of the internal browser"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Will use the internal browser instead of the article viewer"</string>
|
||||||
<string name="pref_general_category_links">"Link handling"</string>
|
<string name="pref_general_category_links">"Link handling"</string>
|
||||||
<string name="pref_general_category_displaying">"Displaying"</string>
|
<string name="pref_general_category_displaying">"Displaying"</string>
|
||||||
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<string name="error_field_required">"Champ requis"</string>
|
<string name="error_field_required">"Champ requis"</string>
|
||||||
<string name="prompt_url">"Url Selfoss"</string>
|
<string name="prompt_url">"Url Selfoss"</string>
|
||||||
<string name="withLoginSwitch">"Avec login ?"</string>
|
<string name="withLoginSwitch">"Avec login ?"</string>
|
||||||
<string name="login_url_problem">"Petit souci. Il manque peut-être un / à la fin ?"</string>
|
<string name="login_url_problem">"Petit souci. Il manque peut être un / à la fin ?"</string>
|
||||||
<string name="prompt_login">"Utilisateur"</string>
|
<string name="prompt_login">"Utilisateur"</string>
|
||||||
<string name="label_share">"Partager"</string>
|
<string name="label_share">"Partager"</string>
|
||||||
<string name="readAll">"Tout lire"</string>
|
<string name="readAll">"Tout lire"</string>
|
||||||
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Afficher le nombre de non lus"</string>
|
<string name="switch_unread_count_title">"Afficher le nombre de non lus"</string>
|
||||||
<string name="display_all_counts_title">"Afficher le nombre de favoris et d'articles lus"</string>
|
<string name="display_all_counts_title">"Afficher le nombre de favoris et d'articles lus"</string>
|
||||||
<string name="text_wrong_url">"Vous semblez essayer de vous connecter avec une URL invalide. Assurez-vous que c'est la bonne, et si le problème persiste, contactez-moi via le lien du play store. Notez aussi que l'application ne peut fonctionner sans l'application web Selfoss. Vous ne pouvez pas utiliser l'application pour accéder directement aux flux RSS."</string>
|
<string name="text_wrong_url">"Vous semblez essayer de vous connecter avec une URL invalide. Assurez-vous que c'est la bonne, et si le problème persiste, contactez-moi via le lien du play store. Notez aussi que l'application ne peut fonctionner sans l'application web Selfoss. Vous ne pouvez pas utiliser l'application pour accéder directement aux flux RSS."</string>
|
||||||
<string name="pref_article_viewer_title">"Ouvrir les liens dans l'application"</string>
|
<string name="pref_general_internal_browser_title">"Ouvrir les liens dans l'application"</string>
|
||||||
<string name="pref_article_viewer_on">"Les articles s'ouvriront dans l'application"</string>
|
<string name="pref_general_internal_browser_on">"Les articles s'ouvriront dans l'application"</string>
|
||||||
<string name="pref_article_viewer_off">"Les articles s'ouvriront dans votre naviguateur par défaut"</string>
|
<string name="pref_general_internal_browser_off">"Les articles s'ouvriront dans votre naviguateur par défaut"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Utiliser le visionneur d'articles"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Utiliser le naviguateur interne"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Utiliser le naviguateur interne au lieu du visionneur d'articles"</string>
|
||||||
<string name="pref_general_category_links">"Gestion des liens"</string>
|
<string name="pref_general_category_links">"Gestion des liens"</string>
|
||||||
<string name="pref_general_category_displaying">"Affichage"</string>
|
<string name="pref_general_category_displaying">"Affichage"</string>
|
||||||
<string name="pref_switch_card_view_on">"Les articles seront affichés en forme de carte"</string>
|
<string name="pref_switch_card_view_on">"Les articles seront affichés en forme de carte"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">La barre sera affichée</string>
|
<string name="reader_static_bar_on">La barre sera affichée</string>
|
||||||
<string name="reader_static_bar_off">La barre sera affichée grâce au bouton</string>
|
<string name="reader_static_bar_off">La barre sera affichée grâce au bouton</string>
|
||||||
<string name="remove_source">Supprimer la source</string>
|
<string name="remove_source">Supprimer la source</string>
|
||||||
<string name="pref_theme_title">Thème Clair/Sombre</string>
|
|
||||||
<string name="mode_dark">Thème sombre</string>
|
|
||||||
<string name="mode_system">Utiliser les paramètres système</string>
|
|
||||||
<string name="mode_light">Thème clair</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Mostrar reconto de artigos non lidos"</string>
|
<string name="switch_unread_count_title">"Mostrar reconto de artigos non lidos"</string>
|
||||||
<string name="display_all_counts_title">"Mostrar reconto de artigos lidos e favoritos"</string>
|
<string name="display_all_counts_title">"Mostrar reconto de artigos lidos e favoritos"</string>
|
||||||
<string name="text_wrong_url">"Semella que intentas usar unha URL non válida. Asegúrate de que é correcta, e se o problema persiste, ponte en contacto conmigo (a través da ligazón de contacto na tenda). Por favor ten en conta que a aplicación precisa que uses Selfoss. Non podes acceder a canles RSS se non o tes."</string>
|
<string name="text_wrong_url">"Semella que intentas usar unha URL non válida. Asegúrate de que é correcta, e se o problema persiste, ponte en contacto conmigo (a través da ligazón de contacto na tenda). Por favor ten en conta que a aplicación precisa que uses Selfoss. Non podes acceder a canles RSS se non o tes."</string>
|
||||||
<string name="pref_article_viewer_title">"Abrir ligazóns dentro da aplicación"</string>
|
<string name="pref_general_internal_browser_title">"Abrir ligazóns dentro da aplicación"</string>
|
||||||
<string name="pref_article_viewer_on">"Os artigos abriranse dentro da aplicación"</string>
|
<string name="pref_general_internal_browser_on">"Os artigos abriranse dentro da aplicación"</string>
|
||||||
<string name="pref_article_viewer_off">"Os artigos abriranse co teu navegador prederminado"</string>
|
<string name="pref_general_internal_browser_off">"Os artigos abriranse co teu navegador prederminado"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Usar o visor de artigos"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Usarase o visor de artigos en lugar do navegador interno"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Usarase o navegador interno en lugar do visor de artigos"</string>
|
||||||
<string name="pref_general_category_links">"Xestión de ligazóns"</string>
|
<string name="pref_general_category_links">"Xestión de ligazóns"</string>
|
||||||
<string name="pref_general_category_displaying">"Visualización"</string>
|
<string name="pref_general_category_displaying">"Visualización"</string>
|
||||||
<string name="pref_switch_card_view_on">"Os artigos amosaranse coma tarxetas"</string>
|
<string name="pref_switch_card_view_on">"Os artigos amosaranse coma tarxetas"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">A barra inferior mostrarase sempre</string>
|
<string name="reader_static_bar_on">A barra inferior mostrarase sempre</string>
|
||||||
<string name="reader_static_bar_off">A barra inferior pode mostrarse a través do botón flotante</string>
|
<string name="reader_static_bar_off">A barra inferior pode mostrarse a través do botón flotante</string>
|
||||||
<string name="remove_source">Eliminar fonte</string>
|
<string name="remove_source">Eliminar fonte</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Tampilkan jumlah item yang belum dibaca"</string>
|
<string name="switch_unread_count_title">"Tampilkan jumlah item yang belum dibaca"</string>
|
||||||
<string name="display_all_counts_title">"Tampilkan jumlah item untuk favorit dan sudah dibaca"</string>
|
<string name="display_all_counts_title">"Tampilkan jumlah item untuk favorit dan sudah dibaca"</string>
|
||||||
<string name="text_wrong_url">"Sepertinya Anda mencoba menggunakan URL yang tidak valid. Pastikan itu benar, jika masalah terus berlanjut, hubungi saya (melalui link kontak toko). Harap dicatat bahwa aplikasi ini mengharuskan Anda menggunakan Selfoss. Tanpa itu, Anda tidak bisa mengakses umpan RSS."</string>
|
<string name="text_wrong_url">"Sepertinya Anda mencoba menggunakan URL yang tidak valid. Pastikan itu benar, jika masalah terus berlanjut, hubungi saya (melalui link kontak toko). Harap dicatat bahwa aplikasi ini mengharuskan Anda menggunakan Selfoss. Tanpa itu, Anda tidak bisa mengakses umpan RSS."</string>
|
||||||
<string name="pref_article_viewer_title">"Buka tautan dalam aplikasi"</string>
|
<string name="pref_general_internal_browser_title">"Buka tautan dalam aplikasi"</string>
|
||||||
<string name="pref_article_viewer_on">"Artikel akan dibuka di dalam aplikasi"</string>
|
<string name="pref_general_internal_browser_on">"Artikel akan dibuka di dalam aplikasi"</string>
|
||||||
<string name="pref_article_viewer_off">"Artikel akan dibuka dalam peramban bawaan Anda"</string>
|
<string name="pref_general_internal_browser_off">"Artikel akan dibuka dalam peramban bawaan Anda"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Gunakan pratinjau artikel"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Lihat artikel di penampil daripada peramban internal"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Gunakan peramban internal dan bukan penampil artikel"</string>
|
||||||
<string name="pref_general_category_links">"Pengolahan tautan"</string>
|
<string name="pref_general_category_links">"Pengolahan tautan"</string>
|
||||||
<string name="pref_general_category_displaying">"Tampilan"</string>
|
<string name="pref_general_category_displaying">"Tampilan"</string>
|
||||||
<string name="pref_switch_card_view_on">"Artikel ini akan ditampilkan dalam bentuk kartu"</string>
|
<string name="pref_switch_card_view_on">"Artikel ini akan ditampilkan dalam bentuk kartu"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Display unread count"</string>
|
<string name="switch_unread_count_title">"Display unread count"</string>
|
||||||
<string name="display_all_counts_title">"Display count for favorite and read"</string>
|
<string name="display_all_counts_title">"Display count for favorite and read"</string>
|
||||||
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
||||||
<string name="pref_article_viewer_title">"Open links inside the app"</string>
|
<string name="pref_general_internal_browser_title">"Open links inside the app"</string>
|
||||||
<string name="pref_article_viewer_on">"Articles will open inside the app"</string>
|
<string name="pref_general_internal_browser_on">"Articles will open inside the app"</string>
|
||||||
<string name="pref_article_viewer_off">"Articles will open with your default browser"</string>
|
<string name="pref_general_internal_browser_off">"Articles will open with your default browser"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Use the article viewer"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Will use the article viewer instead of the internal browser"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Will use the internal browser instead of the article viewer"</string>
|
||||||
<string name="pref_general_category_links">"Link handling"</string>
|
<string name="pref_general_category_links">"Link handling"</string>
|
||||||
<string name="pref_general_category_displaying">"Displaying"</string>
|
<string name="pref_general_category_displaying">"Displaying"</string>
|
||||||
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Display unread count"</string>
|
<string name="switch_unread_count_title">"Display unread count"</string>
|
||||||
<string name="display_all_counts_title">"Display count for favorite and read"</string>
|
<string name="display_all_counts_title">"Display count for favorite and read"</string>
|
||||||
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
||||||
<string name="pref_article_viewer_title">"Open links inside the app"</string>
|
<string name="pref_general_internal_browser_title">"Open links inside the app"</string>
|
||||||
<string name="pref_article_viewer_on">"Articles will open inside the app"</string>
|
<string name="pref_general_internal_browser_on">"Articles will open inside the app"</string>
|
||||||
<string name="pref_article_viewer_off">"Articles will open with your default browser"</string>
|
<string name="pref_general_internal_browser_off">"Articles will open with your default browser"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Use the article viewer"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Will use the article viewer instead of the internal browser"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Will use the internal browser instead of the article viewer"</string>
|
||||||
<string name="pref_general_category_links">"Link handling"</string>
|
<string name="pref_general_category_links">"Link handling"</string>
|
||||||
<string name="pref_general_category_displaying">"Displaying"</string>
|
<string name="pref_general_category_displaying">"Displaying"</string>
|
||||||
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<style name="NoBar" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
|
||||||
<item name="colorAccentDark">@color/colorAccentDark</item>
|
|
||||||
<item name="preferenceTheme">@style/PreferenceStyle</item>
|
|
||||||
<item name="android:statusBarColor">@color/dark</item>
|
|
||||||
<item name="bottomBarBackground">@color/dark</item>
|
|
||||||
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
|
|
||||||
<item name="webviewBackground">@color/dark</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Geef aantal ongelezen weer"</string>
|
<string name="switch_unread_count_title">"Geef aantal ongelezen weer"</string>
|
||||||
<string name="display_all_counts_title">"Geef aantal weer bij favorieten en gelezen"</string>
|
<string name="display_all_counts_title">"Geef aantal weer bij favorieten en gelezen"</string>
|
||||||
<string name="text_wrong_url">"De gebruikte link lijkt onjuist. Controleer deze. Mocht het probleem blijven, neem dan contact met me op (via de contact link in de store). Om deze app te kunnen gebruiken heb je Selfoss nodig."</string>
|
<string name="text_wrong_url">"De gebruikte link lijkt onjuist. Controleer deze. Mocht het probleem blijven, neem dan contact met me op (via de contact link in de store). Om deze app te kunnen gebruiken heb je Selfoss nodig."</string>
|
||||||
<string name="pref_article_viewer_title">"Links opnemen in interne browser"</string>
|
<string name="pref_general_internal_browser_title">"Links opnemen in interne browser"</string>
|
||||||
<string name="pref_article_viewer_on">"Artikelen worden in de interne browser geopend"</string>
|
<string name="pref_general_internal_browser_on">"Artikelen worden in de interne browser geopend"</string>
|
||||||
<string name="pref_article_viewer_off">"Artikelen worden geopend in de standaard browser"</string>
|
<string name="pref_general_internal_browser_off">"Artikelen worden geopend in de standaard browser"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Gebruik artikel viewer"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Artikelen in viewer weergeven in plaats van de interne browser"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Artikelen in interne browser weergeven in plaats van viewer"</string>
|
||||||
<string name="pref_general_category_links">"Links"</string>
|
<string name="pref_general_category_links">"Links"</string>
|
||||||
<string name="pref_general_category_displaying">"Weergave"</string>
|
<string name="pref_general_category_displaying">"Weergave"</string>
|
||||||
<string name="pref_switch_card_view_on">"De artikelen worden als kaarten weergegeven"</string>
|
<string name="pref_switch_card_view_on">"De artikelen worden als kaarten weergegeven"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Exibir contagem de artigos não lidos"</string>
|
<string name="switch_unread_count_title">"Exibir contagem de artigos não lidos"</string>
|
||||||
<string name="display_all_counts_title">"Exibir contagem de lidos e favoritos"</string>
|
<string name="display_all_counts_title">"Exibir contagem de lidos e favoritos"</string>
|
||||||
<string name="text_wrong_url">"Parece que você está tentando utilizar uma URL inválida. Certifique-se de que está correto, e se o problema persistir, entre em contato comigo (através do link de contato da loja). Por favor, note que o aplicativo precisa que você esteja usando o Selfoss. Você não pode acessar feeds RSS sem ele."</string>
|
<string name="text_wrong_url">"Parece que você está tentando utilizar uma URL inválida. Certifique-se de que está correto, e se o problema persistir, entre em contato comigo (através do link de contato da loja). Por favor, note que o aplicativo precisa que você esteja usando o Selfoss. Você não pode acessar feeds RSS sem ele."</string>
|
||||||
<string name="pref_article_viewer_title">"Abrir links dentro do aplicativo"</string>
|
<string name="pref_general_internal_browser_title">"Abrir links dentro do aplicativo"</string>
|
||||||
<string name="pref_article_viewer_on">"Os artigos serão abertos dentro do aplicativo"</string>
|
<string name="pref_general_internal_browser_on">"Os artigos serão abertos dentro do aplicativo"</string>
|
||||||
<string name="pref_article_viewer_off">"Os artigos serão abertos com seu navegador padrão"</string>
|
<string name="pref_general_internal_browser_off">"Os artigos serão abertos com seu navegador padrão"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Use o visualizador de artigos"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Usará o visualizador de artigos em vez do navegador"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Utilizará o navegador em vez do visualizador de artigos"</string>
|
||||||
<string name="pref_general_category_links">"Manipulação de links"</string>
|
<string name="pref_general_category_links">"Manipulação de links"</string>
|
||||||
<string name="pref_general_category_displaying">"Mostrando"</string>
|
<string name="pref_general_category_displaying">"Mostrando"</string>
|
||||||
<string name="pref_switch_card_view_on">"Os artigos serão exibidos no formato de cards"</string>
|
<string name="pref_switch_card_view_on">"Os artigos serão exibidos no formato de cards"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Exibir a contagem não lida"</string>
|
<string name="switch_unread_count_title">"Exibir a contagem não lida"</string>
|
||||||
<string name="display_all_counts_title">"Exibir a contagem para o favorito e leitura"</string>
|
<string name="display_all_counts_title">"Exibir a contagem para o favorito e leitura"</string>
|
||||||
<string name="text_wrong_url">"Você parece estar tentando usar um URL inválido. Certifique-se de que está correto, e se o problema persistir, entre em contato comigo (através do link de contato da loja). Por favor, note que o aplicativo precisa que você esteja usando o Selfoss. Você não pode acessar feeds RSS sem ele."</string>
|
<string name="text_wrong_url">"Você parece estar tentando usar um URL inválido. Certifique-se de que está correto, e se o problema persistir, entre em contato comigo (através do link de contato da loja). Por favor, note que o aplicativo precisa que você esteja usando o Selfoss. Você não pode acessar feeds RSS sem ele."</string>
|
||||||
<string name="pref_article_viewer_title">"Abrir links dentro do app"</string>
|
<string name="pref_general_internal_browser_title">"Abrir links dentro do app"</string>
|
||||||
<string name="pref_article_viewer_on">"Artigos serão aberto dentro do aplicativo"</string>
|
<string name="pref_general_internal_browser_on">"Artigos serão aberto dentro do aplicativo"</string>
|
||||||
<string name="pref_article_viewer_off">"Artigos serão aberto com o seu navegador padrão"</string>
|
<string name="pref_general_internal_browser_off">"Artigos serão aberto com o seu navegador padrão"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Use o Visualizador de artigo"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Vai usar o Visualizador de artigo em vez do navegador interno"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Vai usar o navegador interno em vez do Visualizador de artigo"</string>
|
||||||
<string name="pref_general_category_links">"Manipulação de ligações"</string>
|
<string name="pref_general_category_links">"Manipulação de ligações"</string>
|
||||||
<string name="pref_general_category_displaying">"Mostrando"</string>
|
<string name="pref_general_category_displaying">"Mostrando"</string>
|
||||||
<string name="pref_switch_card_view_on">"Os artigos serão exibidos como cartões"</string>
|
<string name="pref_switch_card_view_on">"Os artigos serão exibidos como cartões"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Display unread count"</string>
|
<string name="switch_unread_count_title">"Display unread count"</string>
|
||||||
<string name="display_all_counts_title">"Display count for favorite and read"</string>
|
<string name="display_all_counts_title">"Display count for favorite and read"</string>
|
||||||
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
||||||
<string name="pref_article_viewer_title">"Open links inside the app"</string>
|
<string name="pref_general_internal_browser_title">"Open links inside the app"</string>
|
||||||
<string name="pref_article_viewer_on">"Articles will open inside the app"</string>
|
<string name="pref_general_internal_browser_on">"Articles will open inside the app"</string>
|
||||||
<string name="pref_article_viewer_off">"Articles will open with your default browser"</string>
|
<string name="pref_general_internal_browser_off">"Articles will open with your default browser"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Use the article viewer"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Will use the article viewer instead of the internal browser"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Will use the internal browser instead of the article viewer"</string>
|
||||||
<string name="pref_general_category_links">"Link handling"</string>
|
<string name="pref_general_category_links">"Link handling"</string>
|
||||||
<string name="pref_general_category_displaying">"Displaying"</string>
|
<string name="pref_general_category_displaying">"Displaying"</string>
|
||||||
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"Okunmamış sayıyı görüntüle"</string>
|
<string name="switch_unread_count_title">"Okunmamış sayıyı görüntüle"</string>
|
||||||
<string name="display_all_counts_title">"Favori ve okunan sayıları göster"</string>
|
<string name="display_all_counts_title">"Favori ve okunan sayıları göster"</string>
|
||||||
<string name="text_wrong_url">"Geçersiz bir URL kullanmaya çalışıyormuş gibi görünüyorsunuz. Doğru olduğundan emin olun ve sorun devam ederse, bana ulaşın (mağaza iletişim bağlantısıyla). Uygulamanın, Selfoss'u kullanmanız gerektiğini lütfen unutmayın. RSS özet akışlarına olmadan erişemezsiniz."</string>
|
<string name="text_wrong_url">"Geçersiz bir URL kullanmaya çalışıyormuş gibi görünüyorsunuz. Doğru olduğundan emin olun ve sorun devam ederse, bana ulaşın (mağaza iletişim bağlantısıyla). Uygulamanın, Selfoss'u kullanmanız gerektiğini lütfen unutmayın. RSS özet akışlarına olmadan erişemezsiniz."</string>
|
||||||
<string name="pref_article_viewer_title">"Uygulamadaki bağlantıları açın"</string>
|
<string name="pref_general_internal_browser_title">"Uygulamadaki bağlantıları açın"</string>
|
||||||
<string name="pref_article_viewer_on">"Makale, uygulama içinde açılacaktır"</string>
|
<string name="pref_general_internal_browser_on">"Makale, uygulama içinde açılacaktır"</string>
|
||||||
<string name="pref_article_viewer_off">"Makaleler varsayılan tarayıcınızla açılır"</string>
|
<string name="pref_general_internal_browser_off">"Makaleler varsayılan tarayıcınızla açılır"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Makale görüntüleyiciyi kullanın"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Dahili tarayıcı yerine makale görüntüleyicisini kullanacak"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Makale görüntüleyicisi yerine dahili tarayıcıyı kullanacak"</string>
|
||||||
<string name="pref_general_category_links">"Bağlantı açma şekli"</string>
|
<string name="pref_general_category_links">"Bağlantı açma şekli"</string>
|
||||||
<string name="pref_general_category_displaying">"Gösteriliyor"</string>
|
<string name="pref_general_category_displaying">"Gösteriliyor"</string>
|
||||||
<string name="pref_switch_card_view_on">"Makaleler kart olarak gösterilecek"</string>
|
<string name="pref_switch_card_view_on">"Makaleler kart olarak gösterilecek"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"显示未读数"</string>
|
<string name="switch_unread_count_title">"显示未读数"</string>
|
||||||
<string name="display_all_counts_title">"显示收藏和已读的计数"</string>
|
<string name="display_all_counts_title">"显示收藏和已读的计数"</string>
|
||||||
<string name="text_wrong_url">"您似乎试图使用无效的 URL。确保它是正确的,如果问题仍然存在,请与我联系 (通过商店的联系链接)。请注意,该应用程序需要您使用 Selfoss。没有它,您无法访问 RSS 源。"</string>
|
<string name="text_wrong_url">"您似乎试图使用无效的 URL。确保它是正确的,如果问题仍然存在,请与我联系 (通过商店的联系链接)。请注意,该应用程序需要您使用 Selfoss。没有它,您无法访问 RSS 源。"</string>
|
||||||
<string name="pref_article_viewer_title">"在应用内打开链接"</string>
|
<string name="pref_general_internal_browser_title">"打开应用程序中的链接"</string>
|
||||||
<string name="pref_article_viewer_on">"文章将在应用程序内打开"</string>
|
<string name="pref_general_internal_browser_on">"文章将在应用程序内打开"</string>
|
||||||
<string name="pref_article_viewer_off">"文章将使用默认浏览器打开"</string>
|
<string name="pref_general_internal_browser_off">"文章将使用默认浏览器打开"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"使用文章查看器"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"将使用文章查看器而不是内部浏览器"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"将使用内部浏览器而不是文章查看器"</string>
|
||||||
<string name="pref_general_category_links">"链接处理"</string>
|
<string name="pref_general_category_links">"链接处理"</string>
|
||||||
<string name="pref_general_category_displaying">"显示"</string>
|
<string name="pref_general_category_displaying">"显示"</string>
|
||||||
<string name="pref_switch_card_view_on">"这些文章将以卡片形式显示"</string>
|
<string name="pref_switch_card_view_on">"这些文章将以卡片形式显示"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">底部栏将始终显示</string>
|
<string name="reader_static_bar_on">底部栏将始终显示</string>
|
||||||
<string name="reader_static_bar_off">底部栏可以通过浮动按钮显示</string>
|
<string name="reader_static_bar_off">底部栏可以通过浮动按钮显示</string>
|
||||||
<string name="remove_source">删除源</string>
|
<string name="remove_source">删除源</string>
|
||||||
<string name="pref_theme_title">浅色/深色模式</string>
|
|
||||||
<string name="mode_dark">深色模式</string>
|
|
||||||
<string name="mode_system">遵循系统设置</string>
|
|
||||||
<string name="mode_light">浅色模式</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -47,9 +47,12 @@
|
|||||||
<string name="switch_unread_count_title">"显示未读数"</string>
|
<string name="switch_unread_count_title">"显示未读数"</string>
|
||||||
<string name="display_all_counts_title">"显示收藏和已读的计数"</string>
|
<string name="display_all_counts_title">"显示收藏和已读的计数"</string>
|
||||||
<string name="text_wrong_url">"您似乎试图使用无效的 URL。确保它是正确的,如果问题仍然存在,请与我联系 (通过商店的联系链接)。请注意,该应用程序需要您使用 Selfoss。没有它,您无法访问 RSS 源。"</string>
|
<string name="text_wrong_url">"您似乎试图使用无效的 URL。确保它是正确的,如果问题仍然存在,请与我联系 (通过商店的联系链接)。请注意,该应用程序需要您使用 Selfoss。没有它,您无法访问 RSS 源。"</string>
|
||||||
<string name="pref_article_viewer_title">"打开应用程序中的链接"</string>
|
<string name="pref_general_internal_browser_title">"打开应用程序中的链接"</string>
|
||||||
<string name="pref_article_viewer_on">"文章将在应用程序内打开"</string>
|
<string name="pref_general_internal_browser_on">"文章将在应用程序内打开"</string>
|
||||||
<string name="pref_article_viewer_off">"文章将使用默认浏览器打开"</string>
|
<string name="pref_general_internal_browser_off">"文章将使用默认浏览器打开"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"使用文章查看器"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"将使用文章查看器而不是内部浏览器"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"将使用内部浏览器而不是文章查看器"</string>
|
||||||
<string name="pref_general_category_links">"链接处理"</string>
|
<string name="pref_general_category_links">"链接处理"</string>
|
||||||
<string name="pref_general_category_displaying">"显示"</string>
|
<string name="pref_general_category_displaying">"显示"</string>
|
||||||
<string name="pref_switch_card_view_on">"这些文章将以卡片形式显示"</string>
|
<string name="pref_switch_card_view_on">"这些文章将以卡片形式显示"</string>
|
||||||
@ -128,8 +131,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -2,8 +2,5 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<declare-styleable name="Theme">
|
<declare-styleable name="Theme">
|
||||||
<attr name="colorAccentDark" format="reference|color" />
|
<attr name="colorAccentDark" format="reference|color" />
|
||||||
<attr name="bottomBarBackground" format="reference|color" />
|
|
||||||
<attr name="toolbarPopupTheme" format="reference|color" />
|
|
||||||
<attr name="webviewBackground" format="reference|color" />
|
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
</resources>
|
</resources>
|
@ -11,5 +11,6 @@
|
|||||||
<color name="refresh_progress_1">@color/colorAccentDark</color>
|
<color name="refresh_progress_1">@color/colorAccentDark</color>
|
||||||
<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="darkBackground">#303030</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string-array name="ModeTitles">
|
|
||||||
<item>@string/mode_light</item>
|
|
||||||
<item>@string/mode_dark</item>
|
|
||||||
<item>@string/mode_system</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="ModeValues">
|
|
||||||
<item>1</item> <!--MODE_NIGHT_NO-->
|
|
||||||
<item>2</item> <!--MODE_NIGHT_YES-->
|
|
||||||
<item>0</item> <!--MODE_NIGHT_AUTO_TIME-->
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="Voice">
|
|
||||||
<item>Male</item>
|
|
||||||
<item>Female</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="VoiceAlias">
|
|
||||||
<item>"usenglishmale"</item>
|
|
||||||
<item>"usenglishfemale"</item>
|
|
||||||
<item>"ukenglishmale"</item>
|
|
||||||
<item>"ukenglishfemale"</item>
|
|
||||||
<item>"eurfrenchmale"</item>
|
|
||||||
<item>"eurfrenchfemale"</item>
|
|
||||||
<item>"eurspanishmale"</item>
|
|
||||||
<item>"eurspanishfemale"</item>
|
|
||||||
<item>"euritalianmale"</item>
|
|
||||||
<item>"euritalianfemale"</item>
|
|
||||||
</string-array>
|
|
||||||
</resources>
|
|
@ -46,9 +46,12 @@
|
|||||||
<string name="switch_unread_count_title">"Display unread count"</string>
|
<string name="switch_unread_count_title">"Display unread count"</string>
|
||||||
<string name="display_all_counts_title">"Display count for favorite and read"</string>
|
<string name="display_all_counts_title">"Display count for favorite and read"</string>
|
||||||
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
||||||
<string name="pref_article_viewer_title">"Open links inside the app"</string>
|
<string name="pref_general_internal_browser_title">"Open links inside the app"</string>
|
||||||
<string name="pref_article_viewer_on">"Articles will open inside the app"</string>
|
<string name="pref_general_internal_browser_on">"Articles will open inside the app"</string>
|
||||||
<string name="pref_article_viewer_off">"Articles will open with your default browser"</string>
|
<string name="pref_general_internal_browser_off">"Articles will open with your default browser"</string>
|
||||||
|
<string name="prefer_article_viewer_title">"Use the article viewer"</string>
|
||||||
|
<string name="prefer_article_viewer_on">"Will use the article viewer instead of the internal browser"</string>
|
||||||
|
<string name="prefer_article_viewer_off">"Will use the internal browser instead of the article viewer"</string>
|
||||||
<string name="pref_general_category_links">"Link handling"</string>
|
<string name="pref_general_category_links">"Link handling"</string>
|
||||||
<string name="pref_general_category_displaying">"Displaying"</string>
|
<string name="pref_general_category_displaying">"Displaying"</string>
|
||||||
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
||||||
@ -130,8 +133,4 @@
|
|||||||
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
<string name="reader_static_bar_on">The bottom bar will always be displayed</string>
|
||||||
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
<string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string>
|
||||||
<string name="remove_source">Remove source</string>
|
<string name="remove_source">Remove source</string>
|
||||||
<string name="pref_theme_title">Light/Dark mode</string>
|
|
||||||
<string name="mode_dark">Dark mode</string>
|
|
||||||
<string name="mode_system">Follow the system setting</string>
|
|
||||||
<string name="mode_light">Light mode</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -4,23 +4,41 @@
|
|||||||
<item name="android:windowBackground">@drawable/background_splash</item>
|
<item name="android:windowBackground">@drawable/background_splash</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="NoBar" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
<style name="NoBar" parent="Theme.MaterialComponents.Light.NoActionBar">
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
<item name="colorAccentDark">@color/colorAccentDark</item>
|
<item name="colorAccentDark">@color/colorAccentDark</item>
|
||||||
<item name="preferenceTheme">@style/PreferenceStyle</item>
|
<item name="cardBackgroundColor">@color/white</item>
|
||||||
<item name="android:statusBarColor">?attr/colorPrimary</item>
|
<item name="android:colorBackground">@color/grey_50</item>
|
||||||
<item name="bottomBarBackground">@color/white</item>
|
<item name="colorSurface">@color/grey_50</item>
|
||||||
|
<item name="android:textColorPrimary">@color/grey_900</item>
|
||||||
|
<item name="android:textColorSecondary">@color/grey_400</item>
|
||||||
|
<item name="materialDrawerStyle">@style/App.materialDrawerStyle</item>
|
||||||
|
<item name="materialDrawerHeaderStyle">@style/Widget.MaterialDrawerHeaderStyle</item>
|
||||||
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
|
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
|
||||||
<item name="webviewBackground">@color/white</item>
|
<item name="preferenceTheme">@style/PreferenceStyle</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Preference Theme -->
|
<style name="NoBarDark" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||||
<style name="PreferenceStyle" parent="@style/PreferenceThemeOverlay">
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="android:tint">?attr/colorOnSurface</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
<item name="colorAccentDark">@color/colorAccentDark</item>
|
||||||
|
<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>
|
||||||
|
<item name="materialDrawerStyle">@style/App.materialDrawerStyle</item>
|
||||||
|
<item name="materialDrawerHeaderStyle">@style/Widget.MaterialDrawerHeaderStyle</item>
|
||||||
|
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>
|
||||||
|
<item name="preferenceTheme">@style/PreferenceStyle</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- ToolBar -->
|
||||||
<style name="ToolBarStyle" parent="Theme.AppCompat">
|
<style name="ToolBarStyle" parent="Theme.AppCompat">
|
||||||
<item name="android:textColorPrimary">@color/white</item>
|
<item name="android:textColorPrimary">@color/white</item>
|
||||||
<item name="android:textColorSecondary">@color/white</item>
|
<item name="android:textColorSecondary">@color/white</item>
|
||||||
@ -28,4 +46,28 @@
|
|||||||
<!--<item name="actionOverflowButtonStyle">@style/ActionButtonOverflowStyle</item>
|
<!--<item name="actionOverflowButtonStyle">@style/ActionButtonOverflowStyle</item>
|
||||||
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>-->
|
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>-->
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- Material Drawer Theme -->
|
||||||
|
<style name="App.materialDrawerStyle" parent="@style/Widget.MaterialDrawerStyle">
|
||||||
|
<item name="materialDrawerPrimaryIcon">?android:textColorPrimary</item>
|
||||||
|
<item name="materialDrawerSecondaryIcon">?android:textColorPrimary</item>
|
||||||
|
<item name="materialDrawerSecondaryText">?android:textColorPrimary</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Preference Theme -->
|
||||||
|
<style name="PreferenceStyle" parent="@style/PreferenceThemeOverlay">
|
||||||
|
<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>
|
</resources>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:defaultValue="20"
|
android:defaultValue="200"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:key="prefer_api_items_number"
|
android:key="prefer_api_items_number"
|
||||||
android:selectAllOnFocus="true"
|
android:selectAllOnFocus="true"
|
||||||
@ -34,10 +34,18 @@
|
|||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
|
android:key="prefer_internal_browser"
|
||||||
|
android:summaryOff="@string/pref_general_internal_browser_off"
|
||||||
|
android:summaryOn="@string/pref_general_internal_browser_on"
|
||||||
|
android:title="@string/pref_general_internal_browser_title"
|
||||||
|
app:iconSpaceReserved="false"/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:dependency="prefer_internal_browser"
|
||||||
android:key="prefer_article_viewer"
|
android:key="prefer_article_viewer"
|
||||||
android:summaryOff="@string/pref_article_viewer_off"
|
android:summaryOff="@string/prefer_article_viewer_off"
|
||||||
android:summaryOn="@string/pref_article_viewer_on"
|
android:summaryOn="@string/prefer_article_viewer_on"
|
||||||
android:title="@string/pref_article_viewer_title"
|
android:title="@string/prefer_article_viewer_title"
|
||||||
app:iconSpaceReserved="false"/>
|
app:iconSpaceReserved="false"/>
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
|
@ -1,13 +1,35 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen 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">
|
||||||
|
<!-- TODO translate this file -->
|
||||||
|
|
||||||
<ListPreference
|
<SwitchPreference
|
||||||
android:defaultValue="0"
|
android:defaultValue="false"
|
||||||
android:entries="@array/ModeTitles"
|
android:key="dark_theme"
|
||||||
android:entryValues="@array/ModeValues"
|
|
||||||
android:key="currentMode"
|
|
||||||
app:iconSpaceReserved="false"
|
app:iconSpaceReserved="false"
|
||||||
android:title="@string/pref_theme_title"
|
android:title="Dark theme" />
|
||||||
app:useSimpleSummaryProvider="false" />
|
|
||||||
|
<com.jaredrummler.android.colorpicker.ColorPreferenceCompat
|
||||||
|
android:defaultValue="@color/colorPrimary"
|
||||||
|
android:key="color_primary"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
android:title="Primary color"/>
|
||||||
|
|
||||||
|
<com.jaredrummler.android.colorpicker.ColorPreferenceCompat
|
||||||
|
android:defaultValue="@color/colorPrimaryDark"
|
||||||
|
android:key="color_primary_dark"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
android:title="Primary dark color"/>
|
||||||
|
|
||||||
|
<com.jaredrummler.android.colorpicker.ColorPreferenceCompat
|
||||||
|
android:defaultValue="@color/colorAccent"
|
||||||
|
android:key="color_accent"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
android:title="Accent color"/>
|
||||||
|
|
||||||
|
<com.jaredrummler.android.colorpicker.ColorPreferenceCompat
|
||||||
|
android:defaultValue="@color/colorAccentDark"
|
||||||
|
android:key="color_accent_dark"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
android:title="Accent dark color"/>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
@ -28,12 +28,12 @@ kotlin {
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
val commonMain by getting {
|
val commonMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("io.ktor:ktor-client-core:2.1.1")
|
implementation("io.ktor:ktor-client-core:2.0.1")
|
||||||
implementation("io.ktor:ktor-client-content-negotiation:2.1.1")
|
implementation("io.ktor:ktor-client-content-negotiation:2.0.1")
|
||||||
implementation("io.ktor:ktor-serialization-kotlinx-json:2.1.1")
|
implementation("io.ktor:ktor-serialization-kotlinx-json:2.0.1")
|
||||||
implementation("io.ktor:ktor-client-logging:2.1.1")
|
implementation("io.ktor:ktor-client-logging:2.0.1")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
|
||||||
implementation("io.ktor:ktor-client-auth:2.1.1")
|
implementation("io.ktor:ktor-client-auth:2.0.1")
|
||||||
implementation("org.jsoup:jsoup:1.14.3")
|
implementation("org.jsoup:jsoup:1.14.3")
|
||||||
|
|
||||||
//Dependency Injection
|
//Dependency Injection
|
||||||
@ -62,7 +62,7 @@ kotlin {
|
|||||||
}
|
}
|
||||||
val androidMain by getting {
|
val androidMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("io.ktor:ktor-client-okhttp:2.1.1")
|
implementation("io.ktor:ktor-client-android:2.0.1")
|
||||||
|
|
||||||
// Sql
|
// Sql
|
||||||
implementation(SqlDelight.android)
|
implementation(SqlDelight.android)
|
||||||
@ -96,7 +96,7 @@ kotlin {
|
|||||||
iosX64Test.dependsOn(this)
|
iosX64Test.dependsOn(this)
|
||||||
iosArm64Test.dependsOn(this)
|
iosArm64Test.dependsOn(this)
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("io.ktor:ktor-client-ios:2.1.1")
|
implementation("io.ktor:ktor-client-ios:2.0.1")
|
||||||
}
|
}
|
||||||
//iosSimulatorArm64Test.dependsOn(this)
|
//iosSimulatorArm64Test.dependsOn(this)
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,7 @@ package bou.amine.apps.readerforselfossv2.model
|
|||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.utils.DateUtils
|
import bou.amine.apps.readerforselfossv2.utils.DateUtils
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
|
||||||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
|
||||||
import kotlinx.serialization.encoding.Decoder
|
|
||||||
import kotlinx.serialization.encoding.Encoder
|
|
||||||
import kotlinx.serialization.json.*
|
|
||||||
|
|
||||||
class SelfossModel {
|
class SelfossModel {
|
||||||
|
|
||||||
@ -57,7 +50,6 @@ class SelfossModel {
|
|||||||
data class Source(
|
data class Source(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val title: String,
|
val title: String,
|
||||||
@Serializable(with = TagsListSerializer::class)
|
|
||||||
val tags: List<String>,
|
val tags: List<String>,
|
||||||
val spout: String,
|
val spout: String,
|
||||||
val error: String,
|
val error: String,
|
||||||
@ -70,15 +62,12 @@ class SelfossModel {
|
|||||||
val datetime: String,
|
val datetime: String,
|
||||||
val title: String,
|
val title: String,
|
||||||
val content: String,
|
val content: String,
|
||||||
@Serializable(with = BooleanSerializer::class)
|
|
||||||
var unread: Boolean,
|
var unread: Boolean,
|
||||||
@Serializable(with = BooleanSerializer::class)
|
|
||||||
var starred: Boolean,
|
var starred: Boolean,
|
||||||
val thumbnail: String?,
|
val thumbnail: String?,
|
||||||
val icon: String?,
|
val icon: String?,
|
||||||
val link: String,
|
val link: String,
|
||||||
val sourcetitle: String,
|
val sourcetitle: String,
|
||||||
@Serializable(with = TagsListSerializer::class)
|
|
||||||
val tags: List<String>
|
val tags: List<String>
|
||||||
) {
|
) {
|
||||||
// TODO: maybe find a better way to handle these kind of urls
|
// TODO: maybe find a better way to handle these kind of urls
|
||||||
@ -117,38 +106,6 @@ class SelfossModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this seems to be super slow.
|
|
||||||
object TagsListSerializer : KSerializer<List<String>> {
|
|
||||||
override fun deserialize(decoder: Decoder): List<String> {
|
|
||||||
return when(val json = ((decoder as JsonDecoder).decodeJsonElement())) {
|
|
||||||
is JsonArray -> json.toList().map { it.toString() }
|
|
||||||
else -> json.toString().split(",")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor
|
|
||||||
get() = PrimitiveSerialDescriptor("tags", PrimitiveKind.STRING)
|
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: List<String>) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object BooleanSerializer : KSerializer<Boolean> {
|
|
||||||
override fun deserialize(decoder: Decoder): Boolean {
|
|
||||||
val json = ((decoder as JsonDecoder).decodeJsonElement()).jsonPrimitive
|
|
||||||
return json.booleanOrNull ?: json.int == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor
|
|
||||||
get() = PrimitiveSerialDescriptor("b", PrimitiveKind.BOOLEAN)
|
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: Boolean) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StatusAndData<T>(val success: Boolean, val data: T? = null) {
|
class StatusAndData<T>(val success: Boolean, val data: T? = null) {
|
||||||
companion object {
|
companion object {
|
||||||
fun <T> succes(d: T): StatusAndData<T> {
|
fun <T> succes(d: T): StatusAndData<T> {
|
||||||
|
@ -49,7 +49,6 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
suspend fun getNewerItems(): ArrayList<SelfossModel.Item> {
|
suspend fun getNewerItems(): ArrayList<SelfossModel.Item> {
|
||||||
// TODO: Use the updatedSince parameter
|
// TODO: Use the updatedSince parameter
|
||||||
var fetchedItems: SelfossModel.StatusAndData<List<SelfossModel.Item>> = SelfossModel.StatusAndData.error()
|
var fetchedItems: SelfossModel.StatusAndData<List<SelfossModel.Item>> = SelfossModel.StatusAndData.error()
|
||||||
var fromDB = false
|
|
||||||
if (isNetworkAvailable()) {
|
if (isNetworkAvailable()) {
|
||||||
fetchedItems = api.getItems(
|
fetchedItems = api.getItems(
|
||||||
displayedItems.type,
|
displayedItems.type,
|
||||||
@ -61,7 +60,6 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if (appSettingsService.isItemCachingEnabled()) {
|
if (appSettingsService.isItemCachingEnabled()) {
|
||||||
fromDB = true
|
|
||||||
fetchedItems = SelfossModel.StatusAndData.succes(
|
fetchedItems = SelfossModel.StatusAndData.succes(
|
||||||
getDBItems().filter {
|
getDBItems().filter {
|
||||||
displayedItems == ItemType.ALL ||
|
displayedItems == ItemType.ALL ||
|
||||||
@ -74,9 +72,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
|
|
||||||
if (fetchedItems.success && fetchedItems.data != null) {
|
if (fetchedItems.success && fetchedItems.data != null) {
|
||||||
items = ArrayList(fetchedItems.data!!)
|
items = ArrayList(fetchedItems.data!!)
|
||||||
if (fromDB) {
|
sortItems()
|
||||||
items.sortByDescending { dateUtils.parseDate(it.datetime) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
@ -97,6 +93,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
|
|
||||||
if (fetchedItems.success && fetchedItems.data != null) {
|
if (fetchedItems.success && fetchedItems.data != null) {
|
||||||
items.addAll(fetchedItems.data!!)
|
items.addAll(fetchedItems.data!!)
|
||||||
|
sortItems()
|
||||||
}
|
}
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
@ -122,6 +119,10 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun sortItems() {
|
||||||
|
items.sortByDescending { dateUtils.parseDate(it.datetime) }
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun reloadBadges(): Boolean {
|
suspend fun reloadBadges(): Boolean {
|
||||||
var success = false
|
var success = false
|
||||||
if (isNetworkAvailable()) {
|
if (isNetworkAvailable()) {
|
||||||
|
@ -15,6 +15,7 @@ class AppSettingsService {
|
|||||||
|
|
||||||
// User settings related
|
// User settings related
|
||||||
private var _itemsCaching: Boolean? = null
|
private var _itemsCaching: Boolean? = null
|
||||||
|
private var _internalBrowser: Boolean? = null
|
||||||
private var _articleViewer: Boolean? = null
|
private var _articleViewer: Boolean? = null
|
||||||
private var _shouldBeCardView: Boolean? = null
|
private var _shouldBeCardView: Boolean? = null
|
||||||
private var _displayUnreadCount: Boolean? = null
|
private var _displayUnreadCount: Boolean? = null
|
||||||
@ -87,7 +88,7 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun refreshItemsNumber() {
|
fun refreshItemsNumber() {
|
||||||
_itemsNumber = settings.getString("prefer_api_items_number", "20").toInt()
|
_itemsNumber = settings.getString("prefer_api_items_number", "200").toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getApiTimeout(): Long {
|
fun getApiTimeout(): Long {
|
||||||
@ -114,6 +115,17 @@ class AppSettingsService {
|
|||||||
_password = settings.getString("password", "")
|
_password = settings.getString("password", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun refreshInternalBrowserEnabled() {
|
||||||
|
_internalBrowser = settings.getBoolean("prefer_internal_browser", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isInternalBrowserEnabled(): Boolean {
|
||||||
|
if (_internalBrowser != null) {
|
||||||
|
refreshInternalBrowserEnabled()
|
||||||
|
}
|
||||||
|
return _internalBrowser == true
|
||||||
|
}
|
||||||
|
|
||||||
private fun refreshArticleViewerEnabled() {
|
private fun refreshArticleViewerEnabled() {
|
||||||
_articleViewer = settings.getBoolean("prefer_article_viewer", true)
|
_articleViewer = settings.getBoolean("prefer_article_viewer", true)
|
||||||
}
|
}
|
||||||
@ -328,6 +340,7 @@ class AppSettingsService {
|
|||||||
fun refreshUserSettings() {
|
fun refreshUserSettings() {
|
||||||
refreshItemsNumber()
|
refreshItemsNumber()
|
||||||
refreshApiTimeout()
|
refreshApiTimeout()
|
||||||
|
refreshInternalBrowserEnabled()
|
||||||
refreshArticleViewerEnabled()
|
refreshArticleViewerEnabled()
|
||||||
refreshShouldBeCardViewEnabled()
|
refreshShouldBeCardViewEnabled()
|
||||||
refreshDisplayUnreadCountEnabled()
|
refreshDisplayUnreadCountEnabled()
|
||||||
|
Loading…
Reference in New Issue
Block a user