Compare commits

..

13 Commits

62 changed files with 865 additions and 1967 deletions

View File

@ -1,3 +0,0 @@
package bou.amine.apps.readerforselfossv2.android
// TODO: test source adding

View File

@ -1,102 +0,0 @@
package bou.amine.apps.readerforselfossv2.android
import android.content.Context
import android.content.Intent
import androidx.test.InstrumentationRegistry
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
import androidx.test.espresso.action.ViewActions.pressKey
import androidx.test.espresso.action.ViewActions.typeText
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.AndroidJUnit4
import android.view.KeyEvent
import androidx.test.espresso.matcher.RootMatchers.isDialog
import bou.amine.apps.readerforselfossv2.android.HomeActivity
import bou.amine.apps.readerforselfossv2.android.LoginActivity
import bou.amine.apps.readerforselfossv2.android.utils.Config
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class HomeActivityEspressoTest {
lateinit var context: Context
@Rule @JvmField
val rule = ActivityTestRule(HomeActivity::class.java, true, false)
@Before
fun clearData() {
context = InstrumentationRegistry.getInstrumentation().targetContext
val editor =
context
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
.edit()
editor.clear()
editor.putString("url", BuildConfig.LOGIN_URL)
editor.putString("login", BuildConfig.LOGIN_USERNAME)
editor.putString("password", BuildConfig.LOGIN_PASSWORD)
editor.commit()
Intents.init()
}
@Test
fun menuItems() {
rule.launchActivity(Intent())
onView(
withMenu(
id = R.id.action_search,
titleId = R.string.menu_home_search
)
).perform(click())
onView(withId(R.id.search_bar)).check(matches(isDisplayed()))
onView(withId(R.id.search_src_text)).perform(
typeText("android"),
pressKey(KeyEvent.KEYCODE_SEARCH),
closeSoftKeyboard()
)
onView(withContentDescription(R.string.abc_toolbar_collapse_description)).perform(click())
openActionBarOverflowOrOptionsMenu(context)
onView(withMenu(id = R.id.refresh, titleId = R.string.menu_home_refresh))
.perform(click())
onView(withText(android.R.string.ok))
.inRoot(isDialog()).check(matches(isDisplayed())).perform(click())
openActionBarOverflowOrOptionsMenu(context)
onView(withText(R.string.action_disconnect)).perform(click())
intended(hasComponent(LoginActivity::class.java.name))
}
// TODO: test articles opening and actions for cards and lists
@After
fun releaseIntents() {
Intents.release()
}
}

View File

@ -1,180 +0,0 @@
package bou.amine.apps.readerforselfossv2.android
import android.content.Context
import android.content.Intent
import androidx.test.InstrumentationRegistry
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
import androidx.test.espresso.action.ViewActions.pressBack
import androidx.test.espresso.action.ViewActions.typeText
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.Intents.times
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.AndroidJUnit4
import bou.amine.apps.readerforselfossv2.android.HomeActivity
import bou.amine.apps.readerforselfossv2.android.LoginActivity
import bou.amine.apps.readerforselfossv2.android.utils.Config
import com.mikepenz.aboutlibraries.ui.LibsActivity
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class LoginActivityEspressoTest {
@Rule @JvmField
val rule = ActivityTestRule(LoginActivity::class.java, true, false)
private lateinit var context: Context
private lateinit var url: String
private lateinit var username: String
private lateinit var password: String
@Before
fun setUp() {
context = InstrumentationRegistry.getInstrumentation().targetContext
val editor =
context
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
.edit()
editor.clear()
editor.commit()
url = BuildConfig.LOGIN_URL
username = BuildConfig.LOGIN_USERNAME
password = BuildConfig.LOGIN_PASSWORD
Intents.init()
}
@Test
fun menuItems() {
rule.launchActivity(Intent())
openActionBarOverflowOrOptionsMenu(context)
onView(withText(R.string.action_about)).perform(click())
intended(hasComponent(LibsActivity::class.java.name), times(1))
onView(isRoot()).perform(pressBack())
intended(hasComponent(LoginActivity::class.java.name))
}
@Test
fun wrongLoginUrl() {
rule.launchActivity(Intent())
onView(withId(R.id.loginProgress))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
onView(withId(R.id.urlView)).perform(click()).perform(typeText("WRONGURL"))
onView(withId(R.id.signInButton)).perform(click())
onView(withId(R.id.urlView)).check(matches(isHintOrErrorEnabled()))
}
// TODO: Add tests for multiple false urls with dialog
@Test
fun emptyAuthData() {
rule.launchActivity(Intent())
onView(withId(R.id.urlView)).perform(click()).perform(typeText(url), closeSoftKeyboard())
onView(withId(R.id.withLogin)).perform(click())
onView(withId(R.id.signInButton)).perform(click())
onView(withId(R.id.loginView)).check(matches(isHintOrErrorEnabled()))
onView(withId(R.id.passwordView)).check(matches(isHintOrErrorEnabled()))
onView(withId(R.id.loginView)).perform(click()).perform(
typeText(username),
closeSoftKeyboard()
)
onView(withId(R.id.passwordView)).check(matches(isHintOrErrorEnabled()))
onView(withId(R.id.signInButton)).perform(click())
onView(withId(R.id.passwordView)).check(
matches(
isHintOrErrorEnabled()
)
)
}
@Test
fun wrongAuthData() {
rule.launchActivity(Intent())
onView(withId(R.id.urlView)).perform(click()).perform(typeText(url), closeSoftKeyboard())
onView(withId(R.id.withLogin)).perform(click())
onView(withId(R.id.loginView)).perform(click()).perform(
typeText(username),
closeSoftKeyboard()
)
onView(withId(R.id.passwordView)).perform(click()).perform(
typeText("WRONGPASS"),
closeSoftKeyboard()
)
onView(withId(R.id.signInButton)).perform(click())
onView(withId(R.id.urlView)).check(matches(isHintOrErrorEnabled()))
onView(withId(R.id.loginView)).check(matches(isHintOrErrorEnabled()))
onView(withId(R.id.passwordView)).check(matches(isHintOrErrorEnabled()))
}
@Test
fun workingAuth() {
rule.launchActivity(Intent())
onView(withId(R.id.urlView)).perform(click()).perform(typeText(url), closeSoftKeyboard())
onView(withId(R.id.withLogin)).perform(click())
onView(withId(R.id.loginView)).perform(click()).perform(
typeText(username),
closeSoftKeyboard()
)
onView(withId(R.id.passwordView)).perform(click()).perform(
typeText(password),
closeSoftKeyboard()
)
onView(withId(R.id.signInButton)).perform(click())
Thread.sleep(2000)
intended(hasComponent(HomeActivity::class.java.name))
}
@After
fun releaseIntents() {
Intents.release()
}
}

View File

@ -1,81 +0,0 @@
package bou.amine.apps.readerforselfossv2.android
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.test.InstrumentationRegistry.getInstrumentation
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.Intents.times
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.AndroidJUnit4
import bou.amine.apps.readerforselfossv2.android.HomeActivity
import bou.amine.apps.readerforselfossv2.android.LoginActivity
import bou.amine.apps.readerforselfossv2.android.MainActivity
import bou.amine.apps.readerforselfossv2.android.utils.Config
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class MainActivityEspressoTest {
lateinit var intent: Intent
lateinit var preferencesEditor: SharedPreferences.Editor
private lateinit var url: String
private lateinit var username: String
private lateinit var password: String
@Rule @JvmField
val rule = ActivityTestRule(MainActivity::class.java, true, false)
@Before
fun setUp() {
intent = Intent()
val context = getInstrumentation().targetContext
// create a SharedPreferences editor
preferencesEditor = context.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE).edit()
url = BuildConfig.LOGIN_URL
username = BuildConfig.LOGIN_USERNAME
password = BuildConfig.LOGIN_PASSWORD
Intents.init()
}
@Test
fun checkFirstOpenLaunchesIntro() {
preferencesEditor.putString("url", "")
preferencesEditor.putString("password", "")
preferencesEditor.putString("login", "")
preferencesEditor.commit()
rule.launchActivity(intent)
intended(hasComponent(LoginActivity::class.java.name))
intended(hasComponent(HomeActivity::class.java.name), times(0))
}
@Test
fun checkNotFirstOpenLaunchesLogin() {
preferencesEditor.putString("url", url)
preferencesEditor.putString("password", password)
preferencesEditor.putString("login", username)
preferencesEditor.commit()
rule.launchActivity(intent)
intended(hasComponent(MainActivity::class.java.name))
intended(hasComponent(HomeActivity::class.java.name))
}
@After
fun releaseIntents() {
Intents.release()
}
}

View File

@ -1,29 +0,0 @@
package bou.amine.apps.readerforselfossv2.android
import androidx.test.espresso.matcher.ViewMatchers
import android.view.View
import android.widget.EditText
import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.Matchers
import org.hamcrest.TypeSafeMatcher
fun isHintOrErrorEnabled(): Matcher<View> =
object : TypeSafeMatcher<View>() {
override fun describeTo(description: Description?) {
}
override fun matchesSafely(item: View?): Boolean {
if (item !is EditText) {
return false
}
return item.error.isNotEmpty()
}
}
fun withMenu(id: Int, titleId: Int): Matcher<View> =
Matchers.anyOf(
ViewMatchers.withId(id),
ViewMatchers.withText(titleId)
)

View File

@ -7,7 +7,6 @@
<application
android:name=".MyApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
@ -68,10 +67,6 @@
android:name=".ImageActivity">
</activity>
<meta-data
android:name="bou.amine.apps.readerforselfossv2.android.utils.glide.SelfSignedGlideModule"
android:value="GlideModule" />
<meta-data android:name="android.webkit.WebView.MetricsOptOut"
android:value="true" />

View File

@ -9,10 +9,10 @@ import androidx.constraintlayout.widget.ConstraintLayout
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.Config
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid
import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import com.ftinc.scoop.Scoop
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -31,6 +31,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware {
override val di by closestDI()
private val repository : Repository by instance()
private val appSettingsService : AppSettingsService by instance()
override fun onCreate(savedInstanceState: Bundle?) {
appColors = AppColors(this@AddSourceActivity)
@ -81,9 +82,9 @@ class AddSourceActivity : AppCompatActivity(), DIAware {
override fun onResume() {
super.onResume()
val config = Config()
if (config.baseUrl.isEmpty() || !config.baseUrl.isBaseUrlValid(this@AddSourceActivity)) {
val baseUrl = appSettingsService.getBaseUrl()
if (baseUrl.isEmpty() || !baseUrl.isBaseUrlValid(this@AddSourceActivity)) {
mustLoginToAddSource()
} else {
handleSpoutsSpinner(binding.spoutsSpinner, binding.progress, binding.formContainer)

View File

@ -30,13 +30,12 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ActivityHomeBinding
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.Config
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.customtabs.CustomTabActivityHelper
import bou.amine.apps.readerforselfossv2.dao.ACTION
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import bou.amine.apps.readerforselfossv2.utils.*
import com.ashokvarma.bottomnavigation.BottomNavigationBar
import com.ashokvarma.bottomnavigation.BottomNavigationItem
@ -50,15 +49,12 @@ import com.mikepenz.materialdrawer.holder.ColorHolder
import com.mikepenz.materialdrawer.holder.StringHolder
import com.mikepenz.materialdrawer.model.DividerDrawerItem
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.*
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
import com.mikepenz.materialdrawer.util.DrawerImageLoader
import com.mikepenz.materialdrawer.util.addStickyFooterItem
import com.mikepenz.materialdrawer.util.updateBadge
import com.mikepenz.materialdrawer.widget.AccountHeaderView
import com.russhwolf.settings.Settings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -68,9 +64,10 @@ import org.kodein.di.instance
import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread
class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAware {
private val MENU_PREFERENCES = 12302
private val SETTINGS_ACTIVITY: Int = 101111
private val DRAWER_ID_TAGS = 100101L
private val DRAWER_ID_HIDDEN_TAGS = 101100L
private val DRAWER_ID_SOURCES = 100110L
@ -78,24 +75,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
private var items: ArrayList<SelfossModel.Item> = ArrayList()
private var internalBrowser = false
private var articleViewer = false
private var shouldBeCardView = false
private var displayUnreadCount = false
private var displayAllCount = false
private var fullHeightCards: Boolean = false
private var itemsNumber: Int = 200
private var elementsShown: ItemType = ItemType.UNREAD
private var displayAccountHeader: Boolean = false
private var infiniteScroll: Boolean = false
private var lastFetchDone: Boolean = false
private var updateSources: Boolean = true
private var markOnScroll: Boolean = false
private var hiddenTags: List<String> = emptyList()
private var periodicRefresh = false
private var refreshMinutes: Long = 360L
private var refreshWhenChargingOnly = false
private lateinit var tabNewBadge: TextBadgeItem
private lateinit var tabArchiveBadge: TextBadgeItem
@ -105,7 +86,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
private var offset: Int = 0
private var firstVisible: Int = 0
private lateinit var recyclerViewScrollListener: RecyclerView.OnScrollListener
private var settings = Settings()
private lateinit var binding: ActivityHomeBinding
private var recyclerAdapter: RecyclerView.Adapter<*>? = null
@ -114,10 +94,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
private lateinit var tagsBadge: Map<Long, Int>
private lateinit var config: Config
override val di by closestDI()
private val repository : Repository by instance()
private val appSettingsService : AppSettingsService by instance()
data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?)
@ -127,8 +106,9 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
}
override fun onCreate(savedInstanceState: Bundle?) {
// Add appcolors to DI
appColors = AppColors(this@HomeActivity)
config = Config()
super.onCreate(savedInstanceState)
binding = ActivityHomeBinding.inflate(layoutInflater)
@ -155,19 +135,16 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
customTabActivityHelper = CustomTabActivityHelper()
handleBottomBar()
handleDrawer()
initDrawer()
handleSwipeRefreshLayout()
handleSettings()
getElementsAccordingToTab()
CoroutineScope(Dispatchers.Main).launch {
repository.tryToCacheItemsAndGetNewOnes()
}
}
private fun handleSwipeRefreshLayout() {
@ -299,7 +276,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
override fun onResume() {
super.onResume()
// TODO: Make this the only appcolors init
appColors = AppColors(this@HomeActivity)
handleDrawerItems()
@ -308,10 +284,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
reloadLayoutManager()
if (!infiniteScroll) {
binding.recyclerView.setHasFixedSize(true)
} else {
if (appSettingsService.isInfiniteLoadingEnabled()) {
handleInfiniteScroll()
} else {
binding.recyclerView.setHasFixedSize(true)
}
handleBottomBarActions()
@ -330,32 +306,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
customTabActivityHelper.unbindCustomTabsService(this)
}
private fun handleSettings() {
internalBrowser = settings.getBoolean("prefer_internal_browser", true)
articleViewer = settings.getBoolean("prefer_article_viewer", true)
shouldBeCardView = settings.getBoolean("card_view_active", false)
displayUnreadCount = settings.getBoolean("display_unread_count", true)
displayAllCount = settings.getBoolean("display_other_count", false)
fullHeightCards = settings.getBoolean("full_height_cards", false)
itemsNumber = settings.getString("prefer_api_items_number", "200").toInt()
displayAccountHeader = settings.getBoolean("account_header_displaying", false)
infiniteScroll = settings.getBoolean("infinite_loading", false)
updateSources = settings.getBoolean("update_sources", true)
markOnScroll = settings.getBoolean("mark_on_scroll", false)
hiddenTags = if (settings.getString("hidden_tags", "").isNotEmpty()) {
settings.getString("hidden_tags", "").replace("\\s".toRegex(), "").split(",")
} else {
emptyList()
}
periodicRefresh = settings.getBoolean("periodic_refresh", false)
refreshWhenChargingOnly = settings.getBoolean("refresh_when_charging", false)
refreshMinutes = settings.getString("periodic_refresh_minutes", "360").toLong()
if (refreshMinutes <= 15) {
refreshMinutes = 15
}
}
private fun handleThemeBinding() {
val scoop = Scoop.getInstance()
scoop.bind(this, Toppings.PRIMARY.value, binding.toolBar)
@ -370,7 +320,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
scoop.update(Toppings.PRIMARY_DARK.value, appColors.colorPrimaryDark)
}
private fun handleDrawer() {
private fun initDrawer() {
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
Glide.with(this@HomeActivity)
@ -409,61 +359,153 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
binding.drawerContainer.addDrawerListener(drawerListener)
displayAccountHeader =
settings.getBoolean("account_header_displaying", false)
binding.mainDrawer.addStickyFooterItem(
PrimaryDrawerItem().apply {
nameRes = R.string.drawer_report_bug
iconRes = R.drawable.ic_bug_report_black_24dp
isIconTinted = true
onDrawerItemClickListener = { _, _, _ ->
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(Config.trackerUrl))
// Sticky items
addStickyPrimaryItem(R.string.drawer_report_bug, R.drawable.ic_bug_report_black_24dp) { _, _, _ ->
val browserIntent =
Intent(Intent.ACTION_VIEW, Uri.parse(AppSettingsService.trackerUrl))
startActivity(browserIntent)
false
}
})
binding.mainDrawer.addStickyFooterItem(
PrimaryDrawerItem().apply {
nameRes = R.string.title_activity_settings
iconRes = R.drawable.ic_settings_black_24dp
isIconTinted = true
onDrawerItemClickListener = { _, _, _ ->
startActivity(Intent(this@HomeActivity, SettingsActivity::class.java))
addStickyPrimaryItem(R.string.title_activity_settings, R.drawable.ic_settings_black_24dp) { _, _, _ ->
startActivityForResult(Intent(this@HomeActivity, SettingsActivity::class.java), SETTINGS_ACTIVITY)
false
}
})
}
if (displayAccountHeader) {
AccountHeaderView(this).apply {
attachToSliderView(binding.mainDrawer)
addProfiles(
ProfileDrawerItem().apply {
nameText = settings.getString("url", "")
setBackgroundResource(R.drawable.bg)
iconRes = R.mipmap.ic_launcher
selectionListEnabledForSingleProfile = false
private fun addStickyPrimaryItem(name: Int, icon: Int, clickListener: ((v: View?, item: IDrawerItem<*>, position: Int) -> Boolean)?) {
binding.mainDrawer.addStickyFooterItem(
PrimaryDrawerItem().apply {
nameRes = name
iconRes = icon
isIconTinted = true
onDrawerItemClickListener = clickListener
})
}
private fun handleDrawerItems() {
tagsBadge = emptyMap()
binding.mainDrawer.itemAdapter.add(
PrimaryDrawerItem().apply {
nameRes = R.string.drawer_loading
isSelectable = false
}
)
CoroutineScope(Dispatchers.IO).launch {
val drawerData = DrawerData(repository.getDBTags().map { it.toView() },
repository.getDBSources().map { it.toView() })
runOnUiThread {
// Only refresh if there is no data in the DB, or if the `UpdateSources` setting is enabled
if (drawerData.sources?.isEmpty() == true || appSettingsService.isUpdateSourcesEnabled()) {
drawerApiCalls(drawerData)
} else {
handleDrawerData(drawerData, loadedFromCache = true)
}
}
}
}
private fun drawerApiCalls(drawerData: DrawerData) {
CoroutineScope(Dispatchers.Main).launch {
val apiDrawerData = DrawerData(repository.getTags(), repository.getSources())
handleDrawerData(if (drawerData != apiDrawerData) apiDrawerData else drawerData)
}
}
private fun handleDrawerData(drawerData: DrawerData, loadedFromCache: Boolean = false) {
binding.mainDrawer.itemAdapter.clear()
// Filters title with clear action
secondaryItem(withDivider = false, R.string.drawer_item_filters, DRAWER_ID_FILTERS, R.string.drawer_action_clear) { _,_,_ ->
repository.sourceFilter = null
repository.tagFilter = null
binding.mainDrawer.setSelectionAtPosition(-1)
getElementsAccordingToTab()
fetchOnEmptyList()
false
}
// Hidden tags
if (drawerData.tags != null && drawerData.tags.isNotEmpty() && appSettingsService.getHiddenTags().isNotEmpty()) {
secondaryItem(
withDivider = true,
R.string.drawer_item_hidden_tags,
DRAWER_ID_HIDDEN_TAGS
)
handleHiddenTags(drawerData.tags)
}
// Tags
secondaryItem(withDivider = true, R.string.drawer_item_tags, DRAWER_ID_TAGS)
if (drawerData.tags == null && !loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem()
.apply { nameRes = R.string.drawer_error_loading_tags; isSelectable = false }
)
} else {
handleTags(drawerData.tags!!)
}
// Sources
secondaryItem(withDivider = true, R.string.drawer_item_sources, DRAWER_ID_SOURCES, R.string.drawer_action_edit) { v, _, _ ->
startActivity(Intent(v!!.context, SourcesActivity::class.java))
false
}
if (drawerData.sources == null && !loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_error_loading_tags
isSelectable = false
}
)
} else {
handleSources(drawerData.sources!!)
}
// About action
binding.mainDrawer.itemAdapter.add(
DividerDrawerItem(),
PrimaryDrawerItem().apply {
nameRes = R.string.action_about
isSelectable = false
iconRes = R.drawable.ic_info_outline_white_24dp
isIconTinted = true
onDrawerItemClickListener = { _,_,_ ->
LibsBuilder()
.withAboutIconShown(true)
.withAboutVersionShown(true)
.start(this@HomeActivity)
false
}
}
)
}
}
private fun secondaryItem(withDivider: Boolean, name: Int, id: Long, badgeId: Int? = null, clickListener: ((v: View?, item: IDrawerItem<*>, position: Int) -> Boolean)? = null) {
if (withDivider) {
binding.mainDrawer.itemAdapter.add(DividerDrawerItem())
}
// TODO: refactor this.
private fun handleDrawerItems() {
tagsBadge = emptyMap()
fun handleDrawerData(maybeDrawerData: DrawerData?, loadedFromCache: Boolean = false) {
fun createDrawerItem(
it: SelfossModel.Tag
) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem().apply {
nameRes = name
identifier = id
isSelectable = false
if (badgeId != null) {
badgeRes = badgeId
}
onDrawerItemClickListener = clickListener
}
)
}
private fun createDrawerItem(it: SelfossModel.Tag) {
val gd = GradientDrawable()
val gdColor = try {
Color.parseColor(it.color)
} catch (e: IllegalArgumentException) {
appColors.colorPrimary
}
gd.setColor(gdColor)
gd.shape = GradientDrawable.RECTANGLE
gd.setSize(30, 30)
@ -493,59 +535,29 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
binding.mainDrawer.itemAdapter.add(drawerItem)
}
fun handleTags(maybeTags: List<SelfossModel.Tag>?) {
if (maybeTags == null) {
if (loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem()
.apply { nameRes = R.string.drawer_error_loading_tags; isSelectable = false }
)
}
} else {
val filteredTags = maybeTags
.filterNot { hiddenTags.contains(it.tag) }
.sortedBy { it.unread == 0 }
tagsBadge = filteredTags.map {
createDrawerItem(it)
(it.tag.longHash() to it.unread)
}.toMap()
}
private fun handleTags(tags: List<SelfossModel.Tag>) {
val filteredTags = tags
.filterNot { appSettingsService.getHiddenTags().contains(it.tag) }
.sortedBy { it.tag }
createTagItems(filteredTags)
}
fun handleHiddenTags(maybeTags: List<SelfossModel.Tag>?) {
if (maybeTags == null) {
if (loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_error_loading_tags
isSelectable = false
}
)
}
} else {
private fun handleHiddenTags(tags: List<SelfossModel.Tag>) {
val filteredHiddenTags: List<SelfossModel.Tag> =
maybeTags.filter { hiddenTags.contains(it.tag) }
tagsBadge = filteredHiddenTags.map {
tags.filter { appSettingsService.getHiddenTags().contains(it.tag) }
createTagItems(filteredHiddenTags)
}
private fun createTagItems(tags: List<SelfossModel.Tag>) {
tagsBadge = tags.associate {
createDrawerItem(it)
(it.tag.longHash() to it.unread)
}.toMap()
}
}
fun handleSources(maybeSources: List<SelfossModel.Source>?) {
if (maybeSources == null) {
if (loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_error_loading_sources
isSelectable = false
}
)
}
} else {
for (source in maybeSources) {
private fun handleSources(sources: List<SelfossModel.Source>) {
for (source in sources) {
val item = PrimaryDrawerItem().apply {
nameText = source.title.getHtmlDecoded()
identifier = source.id.toLong()
@ -561,151 +573,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
binding.mainDrawer.itemAdapter.add(item)
}
}
}
binding.mainDrawer.itemAdapter.clear()
if (maybeDrawerData != null) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_item_filters
isSelectable = false
identifier = DRAWER_ID_FILTERS
badgeRes = R.string.drawer_action_clear
onDrawerItemClickListener = { _,_,_ ->
repository.sourceFilter = null
repository.tagFilter = null
binding.mainDrawer.setSelectionAtPosition(-1)
getElementsAccordingToTab()
fetchOnEmptyList()
false
}
}
)
if (hiddenTags.isNotEmpty()) {
binding.mainDrawer.itemAdapter.add(
DividerDrawerItem(),
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_item_hidden_tags
identifier = DRAWER_ID_HIDDEN_TAGS
isSelectable = false
}
)
handleHiddenTags(maybeDrawerData.tags)
}
binding.mainDrawer.itemAdapter.add(
DividerDrawerItem(),
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_item_tags
identifier = DRAWER_ID_TAGS
isSelectable = false
}
)
handleTags(maybeDrawerData.tags)
binding.mainDrawer.itemAdapter.add(
DividerDrawerItem(),
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_item_sources
identifier = DRAWER_ID_SOURCES
isSelectable = false
badgeRes = R.string.drawer_action_edit
onDrawerItemClickListener = { v,_,_ ->
startActivity(Intent(v!!.context, SourcesActivity::class.java))
false
}
}
)
handleSources(maybeDrawerData.sources)
binding.mainDrawer.itemAdapter.add(
DividerDrawerItem(),
PrimaryDrawerItem().apply {
nameRes = R.string.action_about
isSelectable = false
iconRes = R.drawable.ic_info_outline_white_24dp
isIconTinted = true
onDrawerItemClickListener = { _,_,_ ->
LibsBuilder()
.withAboutIconShown(true)
.withAboutVersionShown(true)
.start(this@HomeActivity)
false
}
}
)
if (!loadedFromCache) {
if (maybeDrawerData.tags != null) {
thread {
repository.resetDBTagsWithData(maybeDrawerData.tags)
}
}
if (maybeDrawerData.sources != null) {
thread {
repository.resetDBSourcesWithData(maybeDrawerData.sources)
}
}
}
} else {
if (!loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
PrimaryDrawerItem().apply {
nameRes = R.string.no_tags_loaded
identifier = DRAWER_ID_TAGS
isSelectable = false
},
PrimaryDrawerItem().apply {
nameRes = R.string.no_sources_loaded
identifier = DRAWER_ID_SOURCES
isSelectable = false
}
)
}
}
}
fun drawerApiCalls(maybeDrawerData: DrawerData?) {
var tags: List<SelfossModel.Tag>? = null
var sources: List<SelfossModel.Source>?
fun sourcesApiCall() {
CoroutineScope(Dispatchers.Main).launch {
val response = repository.getSources()
if (response != null) {
sources = response
val apiDrawerData = DrawerData(tags, sources)
if ((maybeDrawerData != null && maybeDrawerData != apiDrawerData) || maybeDrawerData == null) {
handleDrawerData(apiDrawerData)
}
} else {
val apiDrawerData = DrawerData(tags, null)
if ((maybeDrawerData != null && maybeDrawerData != apiDrawerData) || maybeDrawerData == null) {
handleDrawerData(apiDrawerData)
}
}
}
}
CoroutineScope(Dispatchers.IO).launch {
tags = repository.getTags()
sourcesApiCall()
}
}
binding.mainDrawer.itemAdapter.add(
PrimaryDrawerItem().apply {
nameRes = R.string.drawer_loading
isSelectable = false
}
)
thread {
val drawerData = DrawerData(repository.getDBTags().map { it.toView() },
repository.getDBSources().map { it.toView() })
runOnUiThread {
handleDrawerData(drawerData, loadedFromCache = true)
drawerApiCalls(drawerData)
}
}
}
private fun reloadLayoutManager() {
val currentManager = binding.recyclerView.layoutManager
@ -714,7 +581,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
// This will only update the layout manager if settings changed
when (currentManager) {
is StaggeredGridLayoutManager ->
if (!shouldBeCardView) {
if (!appSettingsService.isCardViewEnabled()) {
layoutManager = GridLayoutManager(
this,
calculateNoOfColumns()
@ -722,7 +589,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
binding.recyclerView.layoutManager = layoutManager
}
is GridLayoutManager ->
if (shouldBeCardView) {
if (appSettingsService.isCardViewEnabled()) {
layoutManager = StaggeredGridLayoutManager(
calculateNoOfColumns(),
StaggeredGridLayoutManager.VERTICAL
@ -733,7 +600,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
}
else ->
if (currentManager == null) {
if (!shouldBeCardView) {
if (!appSettingsService.isCardViewEnabled()) {
layoutManager = GridLayoutManager(
this,
calculateNoOfColumns()
@ -869,17 +736,13 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
}
if (recyclerAdapter == null) {
if (shouldBeCardView) {
if (appSettingsService.isCardViewEnabled()) {
recyclerAdapter =
ItemCardAdapter(
this,
items,
customTabActivityHelper,
internalBrowser,
articleViewer,
fullHeightCards,
appColors,
config
) {
updateItems(it)
}
@ -889,10 +752,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
this,
items,
customTabActivityHelper,
internalBrowser,
articleViewer,
appColors,
config
) {
updateItems(it)
}
@ -914,7 +774,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
}
private fun reloadBadges() {
if (displayUnreadCount || displayAllCount) {
if (appSettingsService.isDisplayUnreadCountEnabled() || appSettingsService.isDisplayAllCountEnabled()) {
CoroutineScope(Dispatchers.Main).launch {
repository.reloadBadges()
reloadBadgeContent()
@ -923,12 +783,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
}
private fun reloadBadgeContent() {
if (displayUnreadCount) {
if (appSettingsService.isDisplayUnreadCountEnabled()) {
tabNewBadge
.setText(repository.badgeUnread.toString())
.maybeShow()
}
if (displayAllCount) {
if (appSettingsService.isDisplayAllCountEnabled()) {
tabArchiveBadge
.setText(repository.badgeAll.toString())
.maybeShow()
@ -1047,7 +907,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
return true
}
R.id.action_disconnect -> {
return Config.logoutAndRedirect(this, this@HomeActivity)
appSettingsService.clearAll()
val intent = Intent(this, LoginActivity::class.java)
this.startActivity(intent)
this@HomeActivity.finish()
return true
}
else -> return super.onOptionsItemSelected(item)
}
@ -1066,15 +930,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
}
private fun handleRecurringTask() {
if (periodicRefresh) {
if (appSettingsService.isPeriodicRefreshEnabled()) {
val myConstraints = Constraints.Builder()
.setRequiresBatteryNotLow(true)
.setRequiresCharging(refreshWhenChargingOnly)
.setRequiresCharging(appSettingsService.isRefreshWhenChargingOnlyEnabled())
.setRequiresStorageNotLow(true)
.build()
val backgroundWork =
PeriodicWorkRequestBuilder<LoadingWorker>(refreshMinutes, TimeUnit.MINUTES)
PeriodicWorkRequestBuilder<LoadingWorker>(appSettingsService.getRefreshMinutes(), TimeUnit.MINUTES)
.setConstraints(myConstraints)
.addTag("selfoss-loading")
.build()
@ -1083,8 +947,11 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
}
}
private fun handleOfflineActions() {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == SETTINGS_ACTIVITY) {
appSettingsService.refreshUserSettings()
}
}
}

View File

@ -16,8 +16,8 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ActivityLoginBindin
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import com.mikepenz.aboutlibraries.LibsBuilder
import com.russhwolf.settings.Settings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -25,19 +25,17 @@ import org.kodein.di.DIAware
import org.kodein.di.android.closestDI
import org.kodein.di.instance
class LoginActivity() : AppCompatActivity(), DIAware {
class LoginActivity : AppCompatActivity(), DIAware {
private var inValidCount: Int = 0
private var isWithSelfSignedCert = false
private var isWithLogin = false
private var isWithHTTPLogin = false
private val settings = Settings()
private lateinit var appColors: AppColors
private lateinit var binding: ActivityLoginBinding
override val di by closestDI()
private val repository : Repository by instance()
private val appSettingsService : AppSettingsService by instance()
override fun onCreate(savedInstanceState: Bundle?) {
appColors = AppColors(this@LoginActivity)
@ -52,7 +50,7 @@ class LoginActivity() : AppCompatActivity(), DIAware {
handleBaseUrlFail()
if (settings.getString("url", "").isNotEmpty()) {
if (appSettingsService.getBaseUrl().isNotEmpty()) {
goToMain()
}
@ -61,13 +59,6 @@ class LoginActivity() : AppCompatActivity(), DIAware {
private fun handleActions() {
binding.withSelfhostedCert.setOnCheckedChangeListener { _, b ->
isWithSelfSignedCert = !isWithSelfSignedCert
val visi: Int = if (b) View.VISIBLE else View.GONE
binding.warningText.visibility = visi
}
binding.passwordView.setOnEditorActionListener(
TextView.OnEditorActionListener { _, id, _ ->
if (id == R.id.loginView || id == EditorInfo.IME_NULL) {
@ -87,14 +78,6 @@ class LoginActivity() : AppCompatActivity(), DIAware {
binding.loginView.visibility = visi
binding.passwordView.visibility = visi
}
binding.withHttpLogin.setOnCheckedChangeListener { _, b ->
isWithHTTPLogin = !isWithHTTPLogin
val visi: Int = if (b) View.VISIBLE else View.GONE
binding.httpLoginView.visibility = visi
binding.httpPasswordView.visibility = visi
}
}
private fun handleBaseUrlFail() {
@ -117,16 +100,11 @@ class LoginActivity() : AppCompatActivity(), DIAware {
}
private fun preferenceError(t: Throwable) {
settings.remove("url")
settings.remove("login")
settings.remove("httpUserName")
settings.remove("password")
settings.remove("httpPassword")
appSettingsService.resetLoginInformation()
binding.urlView.error = getString(R.string.wrong_infos)
binding.loginView.error = getString(R.string.wrong_infos)
binding.passwordView.error = getString(R.string.wrong_infos)
binding.httpLoginView.error = getString(R.string.wrong_infos)
binding.httpPasswordView.error = getString(R.string.wrong_infos)
}
private fun attemptLogin() {
@ -134,16 +112,12 @@ class LoginActivity() : AppCompatActivity(), DIAware {
// Reset errors.
binding.urlView.error = null
binding.loginView.error = null
binding.httpLoginView.error = null
binding.passwordView.error = null
binding.httpPasswordView.error = null
// Store values at the time of the login attempt.
val url = binding.urlView.text.toString()
val login = binding.loginView.text.toString()
val httpLogin = binding.httpLoginView.text.toString()
val password = binding.passwordView.text.toString()
val httpPassword = binding.httpPasswordView.text.toString()
var cancel = false
var focusView: View? = null
@ -180,30 +154,17 @@ class LoginActivity() : AppCompatActivity(), DIAware {
}
}
if (isWithHTTPLogin) {
if (TextUtils.isEmpty(httpPassword)) {
binding.httpPasswordView.error = getString(R.string.error_invalid_password)
focusView = binding.httpPasswordView
cancel = true
}
if (TextUtils.isEmpty(httpLogin)) {
binding.httpLoginView.error = getString(R.string.error_field_required)
focusView = binding.httpLoginView
cancel = true
}
}
if (cancel) {
focusView?.requestFocus()
} else {
showProgress(true)
repository.refreshLoginInformation(url, login, password, httpLogin, httpPassword, isWithSelfSignedCert)
repository.refreshLoginInformation(url, login, password)
CoroutineScope(Dispatchers.IO).launch {
val result = repository.login()
if (result) {
repository.updateApiVersion()
goToMain()
} else {
CoroutineScope(Dispatchers.Main).launch {

View File

@ -14,19 +14,17 @@ import androidx.lifecycle.ProcessLifecycleOwner
import androidx.multidex.MultiDexApplication
import androidx.preference.PreferenceManager
import bou.amine.apps.readerforselfossv2.DI.networkModule
import bou.amine.apps.readerforselfossv2.android.utils.Config
import bou.amine.apps.readerforselfossv2.android.utils.glide.loadMaybeBasicAuth
import bou.amine.apps.readerforselfossv2.android.viewmodel.AppViewModel
import bou.amine.apps.readerforselfossv2.dao.DriverFactory
import bou.amine.apps.readerforselfossv2.dao.ReaderForSelfossDB
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.ftinc.scoop.Scoop
import com.github.ln_12.library.ConnectivityStatus
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
import com.mikepenz.materialdrawer.util.DrawerImageLoader
import com.russhwolf.settings.Settings
import io.github.aakira.napier.DebugAntilog
import io.github.aakira.napier.Napier
import kotlinx.coroutines.CoroutineScope
@ -49,14 +47,10 @@ class MyApp : MultiDexApplication(), DIAware {
private val viewModel: AppViewModel by instance()
private val connectivityStatus: ConnectivityStatus by instance()
private val driverFactory: DriverFactory by instance()
private lateinit var config: Config
private lateinit var settings : Settings
override fun onCreate() {
super.onCreate()
Napier.base(DebugAntilog())
config = Config()
settings = Settings()
initDrawerImageLoader()
@ -93,11 +87,11 @@ class MyApp : MultiDexApplication(), DIAware {
val name = getString(R.string.notification_channel_sync)
val importance = NotificationManager.IMPORTANCE_LOW
val mChannel = NotificationChannel(Config.syncChannelId, name, importance)
val mChannel = NotificationChannel(AppSettingsService.syncChannelId, name, importance)
val newItemsChannelname = getString(R.string.new_items_channel_sync)
val newItemsChannelimportance = NotificationManager.IMPORTANCE_DEFAULT
val newItemsChannelmChannel = NotificationChannel(Config.newItemsChannelId, newItemsChannelname, newItemsChannelimportance)
val newItemsChannelmChannel = NotificationChannel(AppSettingsService.newItemsChannelId, newItemsChannelname, newItemsChannelimportance)
notificationManager.createNotificationChannel(mChannel)
notificationManager.createNotificationChannel(newItemsChannelmChannel)
@ -108,7 +102,7 @@ class MyApp : MultiDexApplication(), DIAware {
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
Glide.with(imageView.context)
.loadMaybeBasicAuth(config, uri.toString())
.load(uri.toString())
.apply(RequestOptions.fitCenterTransform().placeholder(placeholder))
.into(imageView)
}

View File

@ -14,10 +14,10 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ActivityReaderBindi
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.repository.Repository
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import com.ftinc.scoop.Scoop
import com.russhwolf.settings.Settings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -27,7 +27,6 @@ import org.kodein.di.instance
class ReaderActivity : AppCompatActivity(), DIAware {
private var markOnScroll: Boolean = false
private var currentItem: Int = 0
private lateinit var appColors: AppColors
@ -35,12 +34,9 @@ class ReaderActivity : AppCompatActivity(), DIAware {
private lateinit var binding: ActivityReaderBinding
private var activeAlignment: Int = 1
private val JUSTIFY = 1
private val ALIGN_LEFT = 2
override val di by closestDI()
private val repository: Repository by instance()
private val appSettingsService: AppSettingsService by instance()
private fun showMenuItem(willAddToFavorite: Boolean) {
if (willAddToFavorite) {
@ -58,8 +54,6 @@ class ReaderActivity : AppCompatActivity(), DIAware {
showMenuItem(false)
}
private var settings = Settings()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
appColors = AppColors(this)
@ -76,9 +70,6 @@ class ReaderActivity : AppCompatActivity(), DIAware {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
markOnScroll = settings.getBoolean("mark_on_scroll", false)
activeAlignment = settings.getInt("text_align", JUSTIFY)
if (allItems.isEmpty()) {
finish()
}
@ -98,10 +89,9 @@ class ReaderActivity : AppCompatActivity(), DIAware {
}
private fun readItem(item: SelfossModel.Item) {
if (markOnScroll) {
if (appSettingsService.isMarkOnScrollEnabled()) {
CoroutineScope(Dispatchers.IO).launch {
repository.markAsRead(item)
// TODO: Handle failure
}
}
}
@ -142,7 +132,7 @@ class ReaderActivity : AppCompatActivity(), DIAware {
}
private fun alignmentMenu() {
val showJustify = activeAlignment == ALIGN_LEFT
val showJustify = appSettingsService.getActiveAllignment() == AppSettingsService.ALIGN_LEFT
toolbarMenu.findItem(R.id.align_left).isVisible = !showJustify
toolbarMenu.findItem(R.id.align_justify).isVisible = showJustify
}
@ -211,21 +201,19 @@ class ReaderActivity : AppCompatActivity(), DIAware {
}
}
R.id.align_left -> {
activeAlignment = ALIGN_LEFT
switchAlignmentSetting()
switchAlignmentSetting(AppSettingsService.ALIGN_LEFT)
refreshFragment()
}
R.id.align_justify -> {
activeAlignment = JUSTIFY
switchAlignmentSetting()
switchAlignmentSetting(AppSettingsService.JUSTIFY)
refreshFragment()
}
}
return super.onOptionsItemSelected(item)
}
private fun switchAlignmentSetting() {
settings.putInt("text_align", activeAlignment)
private fun switchAlignmentSetting(allignment: Int) {
appSettingsService.changeAllignment(allignment)
alignmentMenu()
}

View File

@ -10,8 +10,8 @@ import bou.amine.apps.readerforselfossv2.android.adapters.SourcesListAdapter
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.repository.Repository
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository
import com.ftinc.scoop.Scoop
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers

View File

@ -9,14 +9,15 @@ import android.widget.ImageView.ScaleType
import androidx.recyclerview.widget.RecyclerView
import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding
import bou.amine.apps.readerforselfossv2.android.model.*
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.customtabs.CustomTabActivityHelper
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
import bou.amine.apps.readerforselfossv2.utils.getIcon
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
@ -34,11 +35,7 @@ class ItemCardAdapter(
override val app: Activity,
override var items: ArrayList<SelfossModel.Item>,
private val helper: CustomTabActivityHelper,
private val internalBrowser: Boolean,
private val articleViewer: Boolean,
private val fullHeightCards: Boolean,
override val appColors: AppColors,
override val config: Config,
override val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
) : ItemsAdapter<ItemCardAdapter.ViewHolder>() {
private val c: Context = app.baseContext
@ -48,6 +45,7 @@ class ItemCardAdapter(
override val di: DI by closestDI(app)
override val repository : Repository by instance()
override val appSettingsService : AppSettingsService by instance()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = CardItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
@ -67,7 +65,7 @@ class ItemCardAdapter(
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
if (!fullHeightCards) {
if (!appSettingsService.isFullHeightCardsEnabled()) {
binding.itemImage.maxHeight = imageMaxHeight
binding.itemImage.scaleType = ScaleType.CENTER_CROP
}
@ -78,7 +76,7 @@ class ItemCardAdapter(
binding.itemImage.setImageDrawable(null)
} else {
binding.itemImage.visibility = View.VISIBLE
c.bitmapCenterCrop(config, itm.getThumbnail(repository.baseUrl), binding.itemImage)
c.bitmapCenterCrop(itm.getThumbnail(repository.baseUrl), binding.itemImage)
}
if (itm.getIcon(repository.baseUrl).isEmpty()) {
@ -91,7 +89,7 @@ class ItemCardAdapter(
.build(itm.title.getHtmlDecoded().toTextDrawableString(), color)
binding.sourceImage.setImageDrawable(drawable)
} else {
c.circularBitmapDrawable(config, itm.getIcon(repository.baseUrl), binding.sourceImage)
c.circularBitmapDrawable(itm.getIcon(repository.baseUrl), binding.sourceImage)
}
}
}
@ -147,8 +145,8 @@ class ItemCardAdapter(
bindingAdapterPosition,
items[bindingAdapterPosition].getLinkDecoded(),
customTabsIntent,
internalBrowser,
articleViewer,
appSettingsService.isInternalBrowserEnabled(),
appSettingsService.isArticleViewerEnabled(),
app
)
}

View File

@ -6,14 +6,17 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import bou.amine.apps.readerforselfossv2.android.databinding.ListItemBinding
import bou.amine.apps.readerforselfossv2.android.model.*
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.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.circularBitmapDrawable
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.android.utils.openItemUrl
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
import bou.amine.apps.readerforselfossv2.utils.getIcon
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
@ -27,10 +30,7 @@ class ItemListAdapter(
override val app: Activity,
override var items: ArrayList<SelfossModel.Item>,
private val helper: CustomTabActivityHelper,
private val internalBrowser: Boolean,
private val articleViewer: Boolean,
override val appColors: AppColors,
override val config: Config,
override val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
) : ItemsAdapter<ItemListAdapter.ViewHolder>() {
private val generator: ColorGenerator = ColorGenerator.MATERIAL
@ -38,6 +38,7 @@ class ItemListAdapter(
override val di: DI by closestDI(app)
override val repository : Repository by instance()
override val appSettingsService : AppSettingsService by instance()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
@ -69,10 +70,10 @@ class ItemListAdapter(
binding.itemImage.setImageDrawable(drawable)
} else {
c.circularBitmapDrawable(config, itm.getIcon(repository.baseUrl), binding.itemImage)
c.circularBitmapDrawable(itm.getIcon(repository.baseUrl), binding.itemImage)
}
} else {
c.bitmapCenterCrop(config, itm.getThumbnail(repository.baseUrl), binding.itemImage)
c.bitmapCenterCrop(itm.getThumbnail(repository.baseUrl), binding.itemImage)
}
}
}
@ -95,8 +96,8 @@ class ItemListAdapter(
bindingAdapterPosition,
items[bindingAdapterPosition].getLinkDecoded(),
customTabsIntent,
internalBrowser,
articleViewer,
appSettingsService.isInternalBrowserEnabled(),
appSettingsService.isArticleViewerEnabled(),
app
)
}

View File

@ -6,9 +6,9 @@ import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
import bou.amine.apps.readerforselfossv2.android.utils.Config
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import bou.amine.apps.readerforselfossv2.utils.ItemType
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.CoroutineScope
@ -19,9 +19,9 @@ import org.kodein.di.DIAware
abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapter<VH>(), DIAware {
abstract var items: ArrayList<SelfossModel.Item>
abstract val repository: Repository
abstract val appSettingsService: AppSettingsService
abstract val app: Activity
abstract val appColors: AppColors
abstract val config: Config
abstract val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
fun updateAllItems(items: ArrayList<SelfossModel.Item>) {
@ -94,8 +94,6 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
private fun unreadItemAtIndex(position: Int, showSnackbar: Boolean = true) {
CoroutineScope(Dispatchers.IO).launch {
repository.unmarkAsRead(items[position])
// Todo: SharedItems.unreadItem(app, api, db, items[position])
// TODO: update db
}
notifyItemChanged(position)

View File

@ -11,10 +11,9 @@ import androidx.recyclerview.widget.RecyclerView
import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.android.databinding.SourceListItemBinding
import bou.amine.apps.readerforselfossv2.android.model.toTextDrawableString
import bou.amine.apps.readerforselfossv2.android.utils.Config
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
import bou.amine.apps.readerforselfossv2.utils.getIcon
import com.amulyakhare.textdrawable.TextDrawable
@ -33,7 +32,6 @@ class SourcesListAdapter(
) : RecyclerView.Adapter<SourcesListAdapter.ViewHolder>(), DIAware {
private val c: Context = app.baseContext
private val generator: ColorGenerator = ColorGenerator.MATERIAL
private lateinit var config: Config
private lateinit var binding: SourceListItemBinding
override val di: DI by closestDI(app)
@ -46,7 +44,6 @@ class SourcesListAdapter(
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val itm = items[position]
config = Config()
if (itm.getIcon(repository.baseUrl).isEmpty()) {
val color = generator.getColor(itm.title.getHtmlDecoded())
@ -58,7 +55,7 @@ class SourcesListAdapter(
.build(itm.title.getHtmlDecoded().toTextDrawableString(), color)
binding.itemImage.setImageDrawable(drawable)
} else {
c.circularBitmapDrawable(config, itm.getIcon(repository.baseUrl), binding.itemImage)
c.circularBitmapDrawable(itm.getIcon(repository.baseUrl), binding.itemImage)
}
binding.sourceTitle.text = itm.title.getHtmlDecoded()

View File

@ -14,12 +14,10 @@ import bou.amine.apps.readerforselfossv2.android.MainActivity
import bou.amine.apps.readerforselfossv2.android.MyApp
import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.android.model.preloadImages
import bou.amine.apps.readerforselfossv2.android.utils.Config
import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAccessible
import bou.amine.apps.readerforselfossv2.dao.ACTION
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository
import com.russhwolf.settings.Settings
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -27,39 +25,37 @@ import org.kodein.di.DIAware
import org.kodein.di.instance
import java.util.*
import kotlin.concurrent.schedule
import kotlin.concurrent.thread
class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(context, params), DIAware {
override val di by lazy { (applicationContext as MyApp).di }
private val repository : Repository by instance()
private val appSettingsService : AppSettingsService by instance()
override fun doWork(): Result {
val settings = Settings()
val periodicRefresh = settings.getBoolean("periodic_refresh", false)
if (periodicRefresh && isNetworkAccessible(context)) {
if (appSettingsService.isPeriodicRefreshEnabled() && isNetworkAccessible(context)) {
CoroutineScope(Dispatchers.IO).launch {
val notificationManager =
applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notification =
NotificationCompat.Builder(applicationContext, Config.syncChannelId)
NotificationCompat.Builder(applicationContext, AppSettingsService.syncChannelId)
.setContentTitle(context.getString(R.string.loading_notification_title))
.setContentText(context.getString(R.string.loading_notification_text))
.setOngoing(true)
.setPriority(PRIORITY_LOW)
.setChannelId(Config.syncChannelId)
.setChannelId(AppSettingsService.syncChannelId)
.setSmallIcon(R.drawable.ic_stat_cloud_download_black_24dp)
notificationManager.notify(1, notification.build())
val notifyNewItems = settings.getBoolean("notify_new_items", false)
repository.handleDBActions()
if (appSettingsService.isNotifyNewItemsEnabled()) {
launch {
handleNewItemsNotification(repository.tryToCacheItemsAndGetNewOnes(), notifyNewItems, notificationManager)
handleNewItemsNotification(repository.tryToCacheItemsAndGetNewOnes(), notificationManager)
}
}
}
}
@ -68,7 +64,6 @@ override fun doWork(): Result {
private fun handleNewItemsNotification(
newItems: List<SelfossModel.Item>?,
notifyNewItems: Boolean,
notificationManager: NotificationManager
) {
CoroutineScope(Dispatchers.IO).launch {
@ -76,7 +71,7 @@ override fun doWork(): Result {
val newSize = apiItems.filter { it.unread }.size
if (notifyNewItems && newSize > 0) {
if (newSize > 0) {
val intent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
@ -89,7 +84,7 @@ override fun doWork(): Result {
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, pflags)
val newItemsNotification =
NotificationCompat.Builder(applicationContext, Config.newItemsChannelId)
NotificationCompat.Builder(applicationContext, AppSettingsService.newItemsChannelId)
.setContentTitle(context.getString(R.string.new_items_notification_title))
.setContentText(
context.getString(
@ -98,7 +93,7 @@ override fun doWork(): Result {
)
)
.setPriority(PRIORITY_DEFAULT)
.setChannelId(Config.newItemsChannelId)
.setChannelId(AppSettingsService.newItemsChannelId)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_tab_fiber_new_black_24dp)

View File

@ -24,14 +24,19 @@ import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.android.api.mercury.MercuryApi
import bou.amine.apps.readerforselfossv2.android.api.mercury.ParsedContent
import bou.amine.apps.readerforselfossv2.android.databinding.FragmentArticleBinding
import bou.amine.apps.readerforselfossv2.android.model.*
import bou.amine.apps.readerforselfossv2.android.model.ParecelableItem
import bou.amine.apps.readerforselfossv2.android.model.toModel
import bou.amine.apps.readerforselfossv2.android.model.toParcelable
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
import bou.amine.apps.readerforselfossv2.android.utils.*
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.loadMaybeBasicAuth
import bou.amine.apps.readerforselfossv2.repository.Repository
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.model.SelfossModel
import bou.amine.apps.readerforselfossv2.repository.Repository
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
import bou.amine.apps.readerforselfossv2.utils.getImages
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
@ -41,7 +46,6 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
import com.github.rubensousa.floatingtoolbar.FloatingToolbar
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.russhwolf.settings.Settings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -70,14 +74,12 @@ class ArticleFragment : Fragment(), DIAware {
private lateinit var fab: FloatingActionButton
private lateinit var appColors: AppColors
private lateinit var textAlignment: String
private lateinit var config: Config
private var _binding: FragmentArticleBinding? = null
private val binding get() = _binding!!
override val di : DI by closestDI()
private val repository: Repository by instance()
private var settings = Settings()
private val appSettingsService: AppSettingsService by instance()
private var typeface: Typeface? = null
private var resId: Int = 0
@ -93,7 +95,6 @@ class ArticleFragment : Fragment(), DIAware {
override fun onCreate(savedInstanceState: Bundle?) {
appColors = AppColors(requireActivity())
config = Config()
super.onCreate(savedInstanceState)
@ -117,10 +118,10 @@ class ArticleFragment : Fragment(), DIAware {
contentSource = item.sourceAndDateText(repository.dateUtils)
allImages = item.getImages()
fontSize = settings.getString("reader_font_size", "16").toInt()
staticBar = settings.getBoolean("reader_static_bar", false)
fontSize = appSettingsService.getFontSize()
staticBar = appSettingsService.isStaticBarEnabled()
font = appSettingsService.getFont()
font = settings.getString("reader_font", "")
if (font.isNotEmpty()) {
resId = requireContext().resources.getIdentifier(font, "font", requireContext().packageName)
typeface = try {
@ -213,7 +214,7 @@ class ArticleFragment : Fragment(), DIAware {
Glide
.with(requireContext())
.asBitmap()
.loadMaybeBasicAuth(config, contentImage)
.load(contentImage)
.apply(RequestOptions.fitCenterTransform())
.into(binding.imageView)
} else {
@ -242,7 +243,7 @@ class ArticleFragment : Fragment(), DIAware {
.setTitle(requireContext().getString(R.string.webview_dialog_issue_title))
.setPositiveButton(android.R.string.ok
) { _, _ ->
settings.putBoolean("prefer_article_viewer", false)
appSettingsService.disableArticleViewer()
requireActivity().finish()
}
.create()
@ -258,7 +259,7 @@ class ArticleFragment : Fragment(), DIAware {
}
private fun refreshAlignment() {
textAlignment = when (settings.getInt("text_align", 1)) {
textAlignment = when (appSettingsService.getActiveAllignment()) {
1 -> "justify"
2 -> "left"
else -> "justify"
@ -307,8 +308,7 @@ class ArticleFragment : Fragment(), DIAware {
Glide
.with(requireContext())
.asBitmap()
.loadMaybeBasicAuth(
config,
.load(
response.body()!!.lead_image_url.orEmpty()
)
.apply(RequestOptions.fitCenterTransform())

View File

@ -1,7 +1,9 @@
package bou.amine.apps.readerforselfossv2.android.fragments
import android.os.Bundle
import android.view.*
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import bou.amine.apps.readerforselfossv2.android.databinding.FragmentImageBinding
import com.bumptech.glide.Glide

View File

@ -3,22 +3,26 @@ package bou.amine.apps.readerforselfossv2.android.settings
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.*
import androidx.preference.EditTextPreference
import androidx.preference.PreferenceManager
import android.view.*
import android.text.Editable
import android.text.InputFilter
import android.text.InputType
import android.text.TextWatcher
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.addTextChangedListener
import androidx.preference.EditTextPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import bou.amine.apps.readerforselfossv2.android.R
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.android.utils.Config
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import com.ftinc.scoop.Scoop
import com.russhwolf.settings.Settings
import java.lang.NumberFormatException
private const val TITLE_TAG = "settingsActivityTitle"
@ -174,12 +178,7 @@ class SettingsActivity : AppCompatActivity(),
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id == R.id.clear) {
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")
AppColors.resetColors()
requireActivity().recreate()
}
return super.onOptionsItemSelected(item)
@ -196,17 +195,17 @@ class SettingsActivity : AppCompatActivity(),
setPreferencesFromResource(R.xml.pref_links, rootKey)
preferenceManager.findPreference<Preference>("trackerLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
openUrl(Uri.parse(Config.trackerUrl))
openUrl(Uri.parse(AppSettingsService.trackerUrl))
true
}
preferenceManager.findPreference<Preference>("sourceLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
openUrl(Uri.parse(Config.sourceUrl))
openUrl(Uri.parse(AppSettingsService.sourceUrl))
false
}
preferenceManager.findPreference<Preference>("translation")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
openUrl(Uri.parse(Config.translationUrl))
openUrl(Uri.parse(AppSettingsService.translationUrl))
false
}
}
@ -217,4 +216,11 @@ class SettingsActivity : AppCompatActivity(),
setPreferencesFromResource(R.xml.pref_experimental, rootKey)
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> super.onBackPressed()
}
return super.onOptionsItemSelected(item)
}
}

View File

@ -58,4 +58,15 @@ class AppColors(a: Activity) {
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")
}
}
}

View File

@ -1,62 +0,0 @@
package bou.amine.apps.readerforselfossv2.android.utils
import android.app.Activity
import android.content.Context
import android.content.Intent
import bou.amine.apps.readerforselfossv2.android.LoginActivity
import com.russhwolf.settings.Settings
class Config {
val settings = Settings()
val baseUrl: String
get() = settings.getString("url", "")
val userLogin: String
get() = settings.getString("login", "")
val userPassword: String
get() = settings.getString("password", "")
val httpUserLogin: String
get() = settings.getString("httpUserName", "")
val httpUserPassword: String
get() = settings.getString("httpPassword", "")
companion object {
const val settingsName = "paramsselfoss"
const val feedbackEmail = "aminecmi@pm.me.com"
const val translationUrl = "https://crwd.in/readerforselfoss"
const val sourceUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform"
const val trackerUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/issues"
const val syncChannelId = "sync-channel-id"
const val newItemsChannelId = "new-items-channel-id"
var apiVersion = 0
/* Execute logout and clear all settings to default */
fun logoutAndRedirect(
c: Context,
callingActivity: Activity,
baseUrlFail: Boolean = false
): Boolean {
val settings = Settings()
settings.clear()
val intent = Intent(c, LoginActivity::class.java)
if (baseUrlFail) {
intent.putExtra("baseUrlFail", baseUrlFail)
}
c.startActivity(intent)
callingActivity.finish()
return true
}
}
}

View File

@ -1,43 +0,0 @@
package bou.amine.apps.readerforselfossv2.android.utils
import okhttp3.OkHttpClient
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
fun getUnsafeHttpClient(): OkHttpClient.Builder =
try {
// Create a trust manager that does not validate certificate chains
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate> =
arrayOf()
@Throws(CertificateException::class)
override fun checkClientTrusted(
chain: Array<java.security.cert.X509Certificate>,
authType: String
) {
}
@Throws(CertificateException::class)
override fun checkServerTrusted(
chain: Array<java.security.cert.X509Certificate>,
authType: String
) {
}
})
// Install the all-trusting trust manager
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
val sslSocketFactory = sslContext.socketFactory
OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
.hostnameVerifier { _, _ -> true }
} catch (e: Exception) {
throw RuntimeException(e)
}

View File

@ -7,15 +7,14 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import androidx.browser.customtabs.CustomTabsService;
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;
import bou.amine.apps.readerforselfossv2.android.utils.customtabs.helpers.KeepAliveService;
@SuppressWarnings("ALL")
class CustomTabsHelper {
private static final String TAG = "CustomTabsHelper";

View File

@ -1,11 +1,10 @@
/* From https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/java/com/mikepenz/materialdrawer/app/drawerItems/CustomBaseViewHolder.java */
package bou.amine.apps.readerforselfossv2.android.utils.drawer
import androidx.recyclerview.widget.RecyclerView
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import bou.amine.apps.readerforselfossv2.android.R
open class CustomBaseViewHolder(var view: View) : RecyclerView.ViewHolder(view) {

View File

@ -2,33 +2,26 @@ package bou.amine.apps.readerforselfossv2.android.utils.glide
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.util.Base64
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import android.widget.ImageView
import bou.amine.apps.readerforselfossv2.android.utils.Config
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.load.model.LazyHeaders
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.BitmapImageViewTarget
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
fun Context.bitmapCenterCrop(config: Config, url: String, iv: ImageView) =
fun Context.bitmapCenterCrop(url: String, iv: ImageView) =
Glide.with(this)
.asBitmap()
.loadMaybeBasicAuth(config, url)
.load(url)
.apply(RequestOptions.centerCropTransform())
.into(iv)
fun Context.circularBitmapDrawable(config: Config, url: String, iv: ImageView) =
fun Context.circularBitmapDrawable(url: String, iv: ImageView) =
Glide.with(this)
.asBitmap()
.loadMaybeBasicAuth(config, url)
.load(url)
.apply(RequestOptions.centerCropTransform())
.into(object : BitmapImageViewTarget(iv) {
override fun setResource(resource: Bitmap?) {
@ -41,26 +34,6 @@ fun Context.circularBitmapDrawable(config: Config, url: String, iv: ImageView) =
}
})
fun RequestBuilder<Bitmap>.loadMaybeBasicAuth(config: Config, url: String): RequestBuilder<Bitmap> {
val builder: LazyHeaders.Builder = LazyHeaders.Builder()
if (config.httpUserLogin.isNotEmpty() || config.httpUserPassword.isNotEmpty()) {
val basicAuth = "Basic " + Base64.encodeToString("${config.httpUserLogin}:${config.httpUserPassword}".toByteArray(), Base64.NO_WRAP)
builder.addHeader("Authorization", basicAuth)
}
val glideUrl = GlideUrl(url, builder.build())
return this.load(glideUrl)
}
fun RequestManager.loadMaybeBasicAuth(config: Config, url: String): RequestBuilder<Drawable> {
val builder: LazyHeaders.Builder = LazyHeaders.Builder()
if (config.httpUserLogin.isNotEmpty() || config.httpUserPassword.isNotEmpty()) {
val basicAuth = "Basic " + Base64.encodeToString("${config.httpUserLogin}:${config.httpUserPassword}".toByteArray(), Base64.NO_WRAP)
builder.addHeader("Authorization", basicAuth)
}
val glideUrl = GlideUrl(url, builder.build())
return this.load(glideUrl)
}
fun getBitmapInputStream(bitmap:Bitmap,compressFormat: Bitmap.CompressFormat): InputStream {
val byteArrayOutputStream = ByteArrayOutputStream()
bitmap.compress(compressFormat, 80, byteArrayOutputStream)

View File

@ -1,33 +0,0 @@
package bou.amine.apps.readerforselfossv2.android.utils.glide
import android.content.Context
import bou.amine.apps.readerforselfossv2.android.utils.getUnsafeHttpClient
import com.bumptech.glide.Glide
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.Registry
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.module.GlideModule
import com.russhwolf.settings.Settings
import java.io.InputStream
class SelfSignedGlideModule : GlideModule {
override fun applyOptions(context: Context?, builder: GlideBuilder?) {
}
override fun registerComponents(context: Context?, glide: Glide?, registry: Registry?) {
if (context != null) {
val settings = Settings()
if (settings.getBoolean("isSelfSignedCert", false)) {
val client = getUnsafeHttpClient().build()
registry?.append(
GlideUrl::class.java,
InputStream::class.java,
com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader.Factory(client)
)
}
}
}
}

View File

@ -2,7 +2,6 @@ package bou.amine.apps.readerforselfossv2.android.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.repository.Repository
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M20,8h-2.81c-0.45,-0.78 -1.07,-1.45 -1.82,-1.96L17,4.41 15.59,3l-2.17,2.17C12.96,5.06 12.49,5 12,5c-0.49,0 -0.96,0.06 -1.41,0.17L8.41,3 7,4.41l1.62,1.63C7.88,6.55 7.26,7.22 6.81,8L4,8v2h2.09c-0.05,0.33 -0.09,0.66 -0.09,1v1L4,12v2h2v1c0,0.34 0.04,0.67 0.09,1L4,16v2h2.81c1.04,1.79 2.97,3 5.19,3s4.15,-1.21 5.19,-3L20,18v-2h-2.09c0.05,-0.33 0.09,-0.66 0.09,-1v-1h2v-2h-2v-1c0,-0.34 -0.04,-0.67 -0.09,-1L20,10L20,8zM14,16h-4v-2h4v2zM14,12h-4v-2h4v2z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9c0.83,0 1.5,-0.67 1.5,-1.5 0,-0.39 -0.15,-0.74 -0.39,-1.01 -0.23,-0.26 -0.38,-0.61 -0.38,-0.99 0,-0.83 0.67,-1.5 1.5,-1.5L16,16c2.76,0 5,-2.24 5,-5 0,-4.42 -4.03,-8 -9,-8zM6.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S5.67,9 6.5,9 8,9.67 8,10.5 7.33,12 6.5,12zM9.5,8C8.67,8 8,7.33 8,6.5S8.67,5 9.5,5s1.5,0.67 1.5,1.5S10.33,8 9.5,8zM14.5,8c-0.83,0 -1.5,-0.67 -1.5,-1.5S13.67,5 14.5,5s1.5,0.67 1.5,1.5S15.33,8 14.5,8zM17.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S16.67,9 17.5,9s1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/>
</vector>

View File

@ -82,45 +82,6 @@
android:maxLines="1"
android:visibility="gone" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/withHttpLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/withHttpLoginSwitch" />
<EditText
android:id="@+id/httpLoginView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="username"
android:hint="@string/prompt_http_login"
android:inputType="text"
android:visibility="gone" />
<EditText
android:id="@+id/httpPasswordView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="password"
android:hint="@string/prompt_http_password"
android:inputType="textPassword"
android:visibility="gone" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/withSelfhostedCert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/self_hosted_cert_switch" />
<TextView
android:id="@+id/warningText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/self_signed_cert_warning"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:visibility="gone" />
<Button
android:id="@+id/signInButton"
style="?android:textAppearanceSmall"

View File

@ -3,16 +3,13 @@
<string name="app_name">"Lector per a Selfoss"</string>
<string name="title_activity_login">"Inicia la sessió"</string>
<string name="prompt_password">"Contrasenya"</string>
<string name="prompt_http_password">"Contrasenya HTTP"</string>
<string name="action_sign_in">"Vés-hi"</string>
<string name="error_invalid_password">"La contrasenya és massa curta"</string>
<string name="error_field_required">"Camp necessari"</string>
<string name="prompt_url">"URL"</string>
<string name="withLoginSwitch">"Autenticació (si és necessària)"</string>
<string name="withHttpLoginSwitch">"Autenticació HTTP (si és necessària)"</string>
<string name="login_url_problem">"Pot ser que falti una \"/\" al final de l'url."</string>
<string name="prompt_login">"Nom d'usuari"</string>
<string name="prompt_http_login">"Nom d'usuari HTTP"</string>
<string name="label_share">"Comparteix"</string>
<string name="readAll">"Llegeix-ho tot"</string>
<string name="action_disconnect">"Desconnecta't"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Torneu a comprovar la informació."</string>
<string name="all_posts_not_read">"No s'han llegit totes les publicacions"</string>
<string name="all_posts_read">"S'han llegit totes les publicacions"</string>
<string name="cant_get_favs">"No es poden obtenir preferits"</string>
<string name="cant_get_new_elements">"No es pot accedir als articles nous"</string>
<string name="cant_get_read">"No es poden llegir els articles"</string>
<string name="nothing_here">"No hi ha res"</string>
<string name="tab_new">"Nou"</string>
<string name="tab_read">"Tot"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Informa d'un error o pregunta sobre funcions noves"</string>
<string name="warning_wrong_url">"ADVERTÈNCIA"</string>
<string name="pref_switch_card_view_title">"Visualització de targeta"</string>
<string name="cant_mark_favortie">"No es pot marcar l'article com a preferit"</string>
<string name="cant_unmark_favortie">"No es pot treure l'element de preferits"</string>
<string name="share">"Comparteix"</string>
<string name="rating_prompt_title">"Us agrada l'aplicació?"</string>
<string name="rating_prompt_yes">"Sí."</string>
<string name="rating_prompt_no">"No gaire…"</string>
<string name="rating_prompt_feedback_title">"Ens podeu dir per què?"</string>
<string name="rating_prompt_feedback_yes">"D'acord."</string>
<string name="rating_prompt_feedback_no">"Ara no."</string>
<string name="rating_prompt_rating_title">"Perfecte! Ens podeu puntuar a la Botiga?"</string>
<string name="rating_prompt_rating_yes">"Sí."</string>
<string name="rating_prompt_rating_no">"Ara no."</string>
<string name="rating_prompt_thanks">"Gràcies. La vostra opinió ens ajuda a millorar l'aplicació."</string>
<string name="switch_unread_count">"Mostra el recompte d'articles no llegits amb un distintiu a la barra inferior."</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>
@ -83,17 +65,12 @@
<string name="card_height_on">L\'alçada de les targetes s\'ajustarà al seu contingut</string>
<string name="card_height_off">L\'alçada de les targetes serà fixa</string>
<string name="source_code">Codi font</string>
<string name="cant_mark_read">No es pot marcar l\'article com a llegit</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">S\'ha produït un error en carregar les etiquetes</string>
<string name="drawer_error_loading_sources">S\'ha produït un error en carregar les fonts</string>
<string name="drawer_item_filters">Filtres</string>
<string name="drawer_action_clear">Esborra</string>
<string name="drawer_item_tags">Etiquetes</string>
<string name="drawer_item_sources">Fonts</string>
<string name="drawer_action_edit">Edita</string>
<string name="no_tags_loaded">No s\'ha carregat cap etiqueta</string>
<string name="no_sources_loaded">No s\'ha carregat cap font</string>
<string name="drawer_loading">S\'està carregant…</string>
<string name="menu_home_search">Cerca</string>
<string name="can_delete_source">No es pot suprimir la font</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Temes</string>
<string name="default_theme">Predeterminat</string>
<string name="default_dark_theme">Predeterminat/Fosc</string>
<string name="pref_header_debug">Depuració</string>
<string name="self_hosted_cert_switch">Utilitzeu un certificat autoallotjat?</string>
<string name="self_signed_cert_warning">Per raons de seguretat, els certificats autosignats no seran compatibles per defecte. En activar aquesta opció, sereu responsable de qualsevol problema de seguretat que es pugui produir.</string>
<string name="pref_selfoss_category">API de Selfoss</string>
<string name="pref_api_items_number_title">Nombre d\'elements carregats</string>
<string name="pref_hidden_tags">Etiquetes ocultes</string>
<string name="summary_debug_identifier">Identificador de depuració</string>
<string name="unique_id_to_clipboard">S\'ha copiat l\'identificador al porta-retalls</string>
<string name="display_header_drawer_summary">Mostra una capçalera amb la instància URL de Selfoss al panell lateral.</string>
<string name="display_header_drawer_title">Capçalera de menú</string>
<string name="pref_general_infinite_loading_title">Carrega articles en desplaçar</string>
<string name="translation">Traducció</string>
<string name="cant_open_invalid_url">L\'element URL no és vàlid. Estic intentant solucionar aquest problema perquè l\'aplicació no falli.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Comparteix</string>
<string name="pref_switch_actions_pager_scroll_on">Es marcaran els articles com a llegits en lliscar el dit d\'un article a l\'altre.</string>
<string name="add_to_favs_reader">Afegeix als preferits</string>
<string name="remove_to_favs_reader">Suprimeix dels preferits</string>
<string name="pref_content_reader_font_size">Mida de la lletra del lector darticles</string>
<string name="pref_header_viewer">Visualitzador d\'articles</string>
<string name="refresh_dialog_message">Aquesta acció actualitzarà la vostra instància de Selfoss.</string>
<string name="markall_dialog_message">Aquesta acció marcarà els elements com a llegits.</string>
<string name="pref_switch_actions_pager_scroll">Marca com a llegit en lliscar el dit</string>
<string name="pref_switch_actions_pager_scroll_off">No es marcaran els articles com a llegits en lliscar el dit d\'un article a l\'altre.</string>
<string name="pref_acra_alwaysaccept">Envia informes d\'error automàtics</string>
<string name="pref_acra_alwaysaccept_enabled">S\'enviaran informes d\'error automàticament</string>
<string name="pref_acra_alwaysaccept_disabled">Us preguntarem abans d\'enviar un informe d\'error.</string>
<string name="pref_debug_crash_reports">Informes d\'error</string>
<string name="pref_debug_debug_logs">Registre de depuració (s\'enviarà automàticament)</string>
<string name="acra_login">Habilita el registre</string>
<string name="drawer_item_hidden_tags">Etiquetes ocultes</string>
<string name="unmark">Marca com no llegit</string>
<string name="pref_header_offline">Sense connexió i memòria clau</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Guarda els elements per utilitzar-los sense connexió</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Sense connexió!</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sincronitza els articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Reader für selfoss"</string>
<string name="title_activity_login">"Anmelden"</string>
<string name="prompt_password">"Passwort"</string>
<string name="prompt_http_password">"HTTP Passwort"</string>
<string name="action_sign_in">"Fortfahren"</string>
<string name="error_invalid_password">"Passwort ist nicht lang genug"</string>
<string name="error_field_required">"Pflichtfeld"</string>
<string name="prompt_url">"URL"</string>
<string name="withLoginSwitch">"Anmeldung erforderlich?"</string>
<string name="withHttpLoginSwitch">"HTTP Anmeldung erforderlich?"</string>
<string name="login_url_problem">"Ups. Du musst eventuell ein \"/\" am Ende der URL anhängen."</string>
<string name="prompt_login">"Benutzername"</string>
<string name="prompt_http_login">"HTTP Benutzername"</string>
<string name="label_share">"Teilen"</string>
<string name="readAll">"Alle gelesen"</string>
<string name="action_disconnect">"Verbindung trennen"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Überprüfe deine Angaben noch einmal."</string>
<string name="all_posts_not_read">"Nicht alle Beiträge wurden gelesen"</string>
<string name="all_posts_read">"Alle Beiträge wurden gelesen"</string>
<string name="cant_get_favs">"Favoriten können nicht abgerufen werden"</string>
<string name="cant_get_new_elements">"Neue Artikel können nicht abgerufen werden"</string>
<string name="cant_get_read">"Gelese Artikel können nicht abgerufen werden"</string>
<string name="nothing_here">"Keine Einträge vorhanden"</string>
<string name="tab_new">"Neu"</string>
<string name="tab_read">"Alle"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Melde einen Bug oder rege ein neues Feature an"</string>
<string name="warning_wrong_url">"WARNUNG"</string>
<string name="pref_switch_card_view_title">"Kachelansicht"</string>
<string name="cant_mark_favortie">"Artikel kann nicht als Favorit markiert werden"</string>
<string name="cant_unmark_favortie">"Eintrag kann nicht aus Favoriten entfernt werden"</string>
<string name="share">"Teilen"</string>
<string name="rating_prompt_title">"Gefällt Dir die App?"</string>
<string name="rating_prompt_yes">"Ja!"</string>
<string name="rating_prompt_no">"Nicht wirklich…"</string>
<string name="rating_prompt_feedback_title">"Magst du uns sagen warum?"</string>
<string name="rating_prompt_feedback_yes">"OK!"</string>
<string name="rating_prompt_feedback_no">"Nicht jetzt."</string>
<string name="rating_prompt_rating_title">"Wunderbar! Magst du uns im Play Store bewerten?"</string>
<string name="rating_prompt_rating_yes">"Sicher!"</string>
<string name="rating_prompt_rating_no">"Nicht jetzt."</string>
<string name="rating_prompt_thanks">"Vielen Dank, dein Feedback hilft die App zu verbessern!"</string>
<string name="switch_unread_count">"Zeige die Zahl ungelesener Artikel in der unteren Leiste."</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>
@ -83,17 +65,12 @@
<string name="card_height_on">Kartenhöhe passt sich Inhalt an</string>
<string name="card_height_off">Kartenhöhe ist fix</string>
<string name="source_code">Quellcode</string>
<string name="cant_mark_read">Artikel kann nicht als gelesen markiert werden</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Fehler beim Laden der Tags…</string>
<string name="drawer_error_loading_sources">Fehler beim Laden der Quellen…</string>
<string name="drawer_item_filters">Filter</string>
<string name="drawer_action_clear">leeren</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Quellen</string>
<string name="drawer_action_edit">bearbeiten</string>
<string name="no_tags_loaded">No tags loaded</string>
<string name="no_sources_loaded">Keine Quellen geladen</string>
<string name="drawer_loading">Lade…</string>
<string name="menu_home_search">Suche</string>
<string name="can_delete_source">Can\'t delete the source…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Designs</string>
<string name="default_theme">Standard</string>
<string name="default_dark_theme">Standard (Dunkel)</string>
<string name="pref_header_debug">Debug</string>
<string name="self_hosted_cert_switch">Verwenden Sie einen selbst gehostetes Zertifikat?</string>
<string name="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
<string name="pref_selfoss_category">selfoss API</string>
<string name="pref_api_items_number_title">Loaded items number</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">Debug identifier</string>
<string name="unique_id_to_clipboard">Identifier copied to your clipboard</string>
<string name="display_header_drawer_summary">Display a header with the selfoss instance url on the lateral drawer.</string>
<string name="display_header_drawer_title">Account header</string>
<string name="pref_general_infinite_loading_title">Load more articles on scroll</string>
<string name="translation">Übersetzung</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Teilen</string>
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="add_to_favs_reader">Zu Favoriten hinzufügen</string>
<string name="remove_to_favs_reader">Aus Favoriten entfernen</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">Dies wird alle Elemente als gelesen markieren.</string>
<string name="pref_switch_actions_pager_scroll">Beim Wischen als gelesen markieren</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Fehlerberichte werden automatisch gesendet</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Fehlerberichte</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Protokollierung aktivieren</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Eintrag als ungelesen markieren</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Nicht verbunden !</string>
<string name="network_connectivity_lost">"Die Netzwerkverbindung wurde unterbrochen"</string>
<string name="network_connectivity_retrieved">"Netzwerkverbindung ist jetzt verfügbar"</string>
<string name="pref_switch_periodic_refresh">Synchronisiere Artikel</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Lector para Selfoss"</string>
<string name="title_activity_login">"Iniciar sesión"</string>
<string name="prompt_password">"Contraseña"</string>
<string name="prompt_http_password">"Contraseña HTTP"</string>
<string name="action_sign_in">"Empezar"</string>
<string name="error_invalid_password">"La contraseña no es suficientemente larga"</string>
<string name="error_field_required">"Campo requerido"</string>
<string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"Inicio de sesión requerido ?"</string>
<string name="withHttpLoginSwitch">"Inicio de sesión HTTP requerido ?"</string>
<string name="login_url_problem">"Oops. Puede que necesite añadir un \"/\" al final de la url."</string>
<string name="prompt_login">"Nombre de usuario"</string>
<string name="prompt_http_login">"Nombre de usuario HTTP"</string>
<string name="label_share">"Compartir"</string>
<string name="readAll">"Leer todo"</string>
<string name="action_disconnect">"Desconectar"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Revise sus datos de nuevo."</string>
<string name="all_posts_not_read">"No todas las publicaciones fueron leídas"</string>
<string name="all_posts_read">"Todas las publicaciones fueron leídas"</string>
<string name="cant_get_favs">"No se pueden obtener favoritos"</string>
<string name="cant_get_new_elements">"No puede recibir nuevos artículos"</string>
<string name="cant_get_read">"No puede recibir artículos leídos"</string>
<string name="nothing_here">"Nada aquí"</string>
<string name="tab_new">"Nuevo"</string>
<string name="tab_read">"Todo"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Reportar un error o solicitar una nueva función"</string>
<string name="warning_wrong_url">"ADVERTENCIA"</string>
<string name="pref_switch_card_view_title">"Vista de la tarjeta"</string>
<string name="cant_mark_favortie">"No puede marcar el artículo como favorito"</string>
<string name="cant_unmark_favortie">"No se puede quitar el artículo de favoritos"</string>
<string name="share">"Compartir"</string>
<string name="rating_prompt_title">"¿Disfrutando la aplicación?"</string>
<string name="rating_prompt_yes">"¡Sí!"</string>
<string name="rating_prompt_no">"La verdad es que no…"</string>
<string name="rating_prompt_feedback_title">"¿Puede decirnos por qué?"</string>
<string name="rating_prompt_feedback_yes">"¡Vale!"</string>
<string name="rating_prompt_feedback_no">"Ahora no."</string>
<string name="rating_prompt_rating_title">"¡Excelente! ¿Puede valorarnos en la tienda?"</string>
<string name="rating_prompt_rating_yes">"¡Claro!"</string>
<string name="rating_prompt_rating_no">"No en este momento."</string>
<string name="rating_prompt_thanks">"¡Gracias, sus comentarios ayudan a mejorar la aplicación!"</string>
<string name="switch_unread_count">"Mostrar el recuento no leído como una insignia de la barra inferior."</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>
@ -83,17 +65,12 @@
<string name="card_height_on">Altura de tarjetas se ajustará a su contenido</string>
<string name="card_height_off">Se fijará la altura de la tarjeta</string>
<string name="source_code">Código fuente</string>
<string name="cant_mark_read">No puede marcar el artículo como leído</string>
<string name="cant_mark_unread">No se puede marcar el artículo como no leído</string>
<string name="drawer_error_loading_tags">Error al cargar etiquetas…</string>
<string name="drawer_error_loading_sources">Error al cargar fuentes…</string>
<string name="drawer_item_filters">Filtros</string>
<string name="drawer_action_clear">limpiar</string>
<string name="drawer_item_tags">Etiquetas</string>
<string name="drawer_item_sources">Fuentes</string>
<string name="drawer_action_edit">editar</string>
<string name="no_tags_loaded">No hay etiquetas cargadas</string>
<string name="no_sources_loaded">No hay fuentes cargadas</string>
<string name="drawer_loading">Cargando…</string>
<string name="menu_home_search">Buscar</string>
<string name="can_delete_source">No se puede eliminar la fuente…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Temas</string>
<string name="default_theme">Predeterminado</string>
<string name="default_dark_theme">Predeterminado/Oscuro</string>
<string name="pref_header_debug">Depurar</string>
<string name="self_hosted_cert_switch">Utilizando un certificado alojado propiamente ?</string>
<string name="self_signed_cert_warning">Por razones de seguridad, los certificados propios no son compatibles por defecto. Activando esto, no seré responsable de cualquier problema de seguridad que encuentre.</string>
<string name="pref_selfoss_category">Api de Selfoss</string>
<string name="pref_api_items_number_title">Número de artículos cargados</string>
<string name="pref_hidden_tags">Etiquetas ocultas</string>
<string name="summary_debug_identifier">Identificador de depuración</string>
<string name="unique_id_to_clipboard">Identificador copiado a su portapapeles</string>
<string name="display_header_drawer_summary">Mostrar una cabecera con la url de instancia de selfoss en el cajón lateral.</string>
<string name="display_header_drawer_title">Cabecera de cuenta</string>
<string name="pref_general_infinite_loading_title">Cargar más artículos en desplazamiento</string>
<string name="translation">Traducción</string>
<string name="cant_open_invalid_url">La url del elemento no es válida. Estoy buscando resolver este problema para que la aplicación no colapse.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Compartir</string>
<string name="pref_switch_actions_pager_scroll_on">Marcar artículos como leidos al desplazarse entre ellos.</string>
<string name="add_to_favs_reader">Añadir a Favoritos</string>
<string name="remove_to_favs_reader">Eliminar de favoritos</string>
<string name="pref_content_reader_font_size">Tamaño de la fuente del lector</string>
<string name="pref_header_viewer">Visor de artículos</string>
<string name="refresh_dialog_message">Esto actualizará su instancia de Selfoss.</string>
<string name="markall_dialog_message">Esto marcará todos los artículos como leídos.</string>
<string name="pref_switch_actions_pager_scroll">Marcar artículos como leídos al deslizar con el dedo hacia los lados</string>
<string name="pref_switch_actions_pager_scroll_off">No marcar artículos como leídos al deslizar con el dedo hacia los lados.</string>
<string name="pref_acra_alwaysaccept">Enviar automáticamente informe de fallos</string>
<string name="pref_acra_alwaysaccept_enabled">Se enviaran automáticamente los informes de fallos</string>
<string name="pref_acra_alwaysaccept_disabled">Le preguntará al enviar informes de fallos.</string>
<string name="pref_debug_crash_reports">Informe de fallos</string>
<string name="pref_debug_debug_logs">Registro de depuración (éstos se enviarán sin diálogo)</string>
<string name="acra_login">Habilitar el registro</string>
<string name="drawer_item_hidden_tags">Etiquetas ocultas</string>
<string name="unmark">Marcar artículo como no leído</string>
<string name="pref_header_offline">Sin conexión y caché</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Guardar elementos para uso sin conexión</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Sin conexión!</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sincronizar artículos</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Reader for Selfoss"</string>
<string name="title_activity_login">"Log in"</string>
<string name="prompt_password">"Password"</string>
<string name="prompt_http_password">"HTTP Password"</string>
<string name="action_sign_in">"Go"</string>
<string name="error_invalid_password">"Password not long enough"</string>
<string name="error_field_required">"Field required"</string>
<string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"Login required ?"</string>
<string name="withHttpLoginSwitch">"HTTP Login required ?"</string>
<string name="login_url_problem">"Oops. You may need to add a \"/\" at the end of the url."</string>
<string name="prompt_login">"Username"</string>
<string name="prompt_http_login">"HTTP Username"</string>
<string name="label_share">"Share"</string>
<string name="readAll">"Read all"</string>
<string name="action_disconnect">"Disconnect"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Check your details again."</string>
<string name="all_posts_not_read">"All posts weren't read"</string>
<string name="all_posts_read">"All posts were read"</string>
<string name="cant_get_favs">"Can't get favorites"</string>
<string name="cant_get_new_elements">"Can't get new articles"</string>
<string name="cant_get_read">"Can't get read articles"</string>
<string name="nothing_here">"Nothing here"</string>
<string name="tab_new">"New"</string>
<string name="tab_read">"All"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Report a bug or ask for a new feature"</string>
<string name="warning_wrong_url">"WARNING"</string>
<string name="pref_switch_card_view_title">"Card View"</string>
<string name="cant_mark_favortie">"Can't mark article as favorite"</string>
<string name="cant_unmark_favortie">"Can't remove item from favorite"</string>
<string name="share">"Share"</string>
<string name="rating_prompt_title">"Enjoying the app ?"</string>
<string name="rating_prompt_yes">"Yes !"</string>
<string name="rating_prompt_no">"Not really …"</string>
<string name="rating_prompt_feedback_title">"Can you tell us why ?"</string>
<string name="rating_prompt_feedback_yes">"OK !"</string>
<string name="rating_prompt_feedback_no">"Not now."</string>
<string name="rating_prompt_rating_title">"Great ! Can you rate us on the Store ?"</string>
<string name="rating_prompt_rating_yes">"Sure !"</string>
<string name="rating_prompt_rating_no">"Not right now."</string>
<string name="rating_prompt_thanks">"Thanks, your feedback help enhance the app !"</string>
<string name="switch_unread_count">"Display the unread count as a badge for the bottom bar."</string>
<string name="switch_unread_count_title">"Display unread count"</string>
<string name="display_all_counts_title">"Display count for favorite and read"</string>
@ -83,17 +65,12 @@
<string name="card_height_on">Cards height will adjust to its content</string>
<string name="card_height_off">Card height will be fixed</string>
<string name="source_code">Source code</string>
<string name="cant_mark_read">Can\'t mark article as read</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Error loading tags…</string>
<string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="drawer_item_filters">Filters</string>
<string name="drawer_action_clear">clear</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Sources</string>
<string name="drawer_action_edit">edit</string>
<string name="no_tags_loaded">No tags loaded</string>
<string name="no_sources_loaded">No sources loaded</string>
<string name="drawer_loading">Loading …</string>
<string name="menu_home_search">Search</string>
<string name="can_delete_source">Can\'t delete the source…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Themes</string>
<string name="default_theme">Default</string>
<string name="default_dark_theme">Default/Dark</string>
<string name="pref_header_debug">Debug</string>
<string name="self_hosted_cert_switch">Using a self hosted certificate ?</string>
<string name="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
<string name="pref_selfoss_category">Selfoss Api</string>
<string name="pref_api_items_number_title">Loaded items number</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">Debug identifier</string>
<string name="unique_id_to_clipboard">Identifier copied to your clipboard</string>
<string name="display_header_drawer_summary">Display a header with the selfoss instance url on the lateral drawer.</string>
<string name="display_header_drawer_title">Account header</string>
<string name="pref_general_infinite_loading_title">Load more articles on scroll</string>
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="add_to_favs_reader">Add to favorites</string>
<string name="remove_to_favs_reader">Remove from favorites</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Enable logging</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Mark item as unread</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Reader for Selfoss"</string>
<string name="title_activity_login">"Login"</string>
<string name="prompt_password">"Mot de passe"</string>
<string name="prompt_http_password">"Mot de passe HTTP"</string>
<string name="action_sign_in">"Valider"</string>
<string name="error_invalid_password">"Mot de passe trop court"</string>
<string name="error_field_required">"Champ requis"</string>
<string name="prompt_url">"Url Selfoss"</string>
<string name="withLoginSwitch">"Avec login ?"</string>
<string name="withHttpLoginSwitch">"Avec login HTTP ?"</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_http_login">"Utilisateur HTTP"</string>
<string name="label_share">"Partager"</string>
<string name="readAll">"Tout lire"</string>
<string name="action_disconnect">"Déconnecter"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Vérifiez vos informations."</string>
<string name="all_posts_not_read">"Tous les posts n'ont pas été lus"</string>
<string name="all_posts_read">"Tous les posts sont lus"</string>
<string name="cant_get_favs">"Impossible de récupérer les éléments favoris."</string>
<string name="cant_get_new_elements">"Impossible de récupérer les nouveaux éléments."</string>
<string name="cant_get_read">"Impossible de récupérer les éléments lus."</string>
<string name="nothing_here">"Il n'y a rien ici !"</string>
<string name="tab_new">"Non lus"</string>
<string name="tab_read">"Tous"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Pour signaler un bug ou demander une nouvelle fonctionnalité"</string>
<string name="warning_wrong_url">"ATTENTION"</string>
<string name="pref_switch_card_view_title">"Vue en carte"</string>
<string name="cant_mark_favortie">"Impossible de marquer l'élément comme favoris"</string>
<string name="cant_unmark_favortie">"Impossible de retirer l'élément des favoris"</string>
<string name="share">"Partager"</string>
<string name="rating_prompt_title">"Vous aimez l'application ?"</string>
<string name="rating_prompt_yes">"Oui."</string>
<string name="rating_prompt_no">"Pas vraiment …"</string>
<string name="rating_prompt_feedback_title">"Pouvez-vous nous dire pourquoi ?"</string>
<string name="rating_prompt_feedback_yes">"Oui !"</string>
<string name="rating_prompt_feedback_no">"Pas maintenant."</string>
<string name="rating_prompt_rating_title">"Super ! Pouvez-vous nous noter sur le store ?"</string>
<string name="rating_prompt_rating_yes">"D'accord !"</string>
<string name="rating_prompt_rating_no">"Peut-être plus tard."</string>
<string name="rating_prompt_thanks">"Merci, cela nous aide à améliorer l'application !"</string>
<string name="switch_unread_count">"Afficher le nombre d'articles non lus sur la barre en bas de l'écran"</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>
@ -83,17 +65,12 @@
<string name="card_height_on">La taille de la carte s\'adaptera au contenu</string>
<string name="card_height_off">La taille de la carte sera fixe</string>
<string name="source_code">Code source</string>
<string name="cant_mark_read">Impossible de marquer l\'article comme lu</string>
<string name="cant_mark_unread">Impossible de marquer l\'article comme non lu</string>
<string name="drawer_error_loading_tags">Erreur lors du chargement des tags…</string>
<string name="drawer_error_loading_sources">Erreur lors du chargement des sources…</string>
<string name="drawer_item_filters">Filtres</string>
<string name="drawer_action_clear">raz</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Sources</string>
<string name="drawer_action_edit">éditer</string>
<string name="no_tags_loaded">Pas de tags chargés</string>
<string name="no_sources_loaded">Pas de sources chargés</string>
<string name="drawer_loading">Chargement …</string>
<string name="menu_home_search">Rechercher</string>
<string name="can_delete_source">Impossible de supprimer la source…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Thèmes</string>
<string name="default_theme">Par défaut</string>
<string name="default_dark_theme">Par défaut/Foncé</string>
<string name="pref_header_debug">Debug</string>
<string name="self_hosted_cert_switch">Certificat auto-signé ?</string>
<string name="self_signed_cert_warning">Pour des raisons de sécurité, les certificats auto-signés sont désactivés par défaut. En les activant, je ne serais pas responsable de quelconques problèmes de sécurité rencontrés.</string>
<string name="pref_selfoss_category">Api Selfoss</string>
<string name="pref_api_items_number_title">Nombre d\'articles chargés</string>
<string name="pref_hidden_tags">Tags Cachés</string>
<string name="summary_debug_identifier">Identifiant de debug</string>
<string name="unique_id_to_clipboard">Texte copié</string>
<string name="display_header_drawer_summary">Afficher une entête avec l\'url de votre instance de Selfoss en haut du drawer lateral.</string>
<string name="display_header_drawer_title">Entête de compte</string>
<string name="pref_general_infinite_loading_title">Charger plus d\'articles au scroll</string>
<string name="translation">Traduction</string>
<string name="cant_open_invalid_url">Lurl de lélément nest pas valide. En attendant la résolution du problème, le lien ne s\'ouvrira pas.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Partager</string>
<string name="pref_switch_actions_pager_scroll_on">Marquer les articles comme lus à la navigation dans le lecteur d\'article.</string>
<string name="add_to_favs_reader">Ajouter aux favoris</string>
<string name="remove_to_favs_reader">Supprimer des favoris</string>
<string name="pref_content_reader_font_size">Taille du texte du contenu du lecteur d\'articles</string>
<string name="pref_header_viewer">Lecteur d\'articles</string>
<string name="refresh_dialog_message">En validant, votre instance Selfoss sera mise à jour.</string>
<string name="markall_dialog_message">Marquer tous les éléments comme lus ?</string>
<string name="pref_switch_actions_pager_scroll">Marquer comme lu à la navigation.</string>
<string name="pref_switch_actions_pager_scroll_off">Ne pas marquer les articles comme lus à la navigation.</string>
<string name="pref_acra_alwaysaccept">Envoyer automatiquement les rapports d\'erreur</string>
<string name="pref_acra_alwaysaccept_enabled">Enverra automatiquement les rapports d\'erreur</string>
<string name="pref_acra_alwaysaccept_disabled">Demandera une confirmation à chaque incident.</string>
<string name="pref_debug_crash_reports">Rapport d\'erreur</string>
<string name="pref_debug_debug_logs">Log de debug (seront envoyés automatiquement)</string>
<string name="acra_login">Activer les logs</string>
<string name="drawer_item_hidden_tags">Tags Cachés</string>
<string name="unmark">Marquer l\'article comme non lu</string>
<string name="pref_header_offline">Hors ligne et cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Sauvegarder les articles pour une utilisation hors ligne</string>
<string name="pref_switch_update_sources">Vérifier les nouvelles sources et tags</string>
<string name="pref_switch_update_sources_summary">Désactivez cette option si votre serveur reçoit trop de requêtes.</string>
<string name="no_network_connectivity">Hors connexion !</string>
<string name="network_connectivity_lost">"Connexion au réseau perdue"</string>
<string name="network_connectivity_retrieved">"Connexion réseau de nouveau disponible"</string>
<string name="pref_switch_periodic_refresh">Synchroniser les articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Lector para selfoss"</string>
<string name="title_activity_login">"Conectar"</string>
<string name="prompt_password">"Contrasinal"</string>
<string name="prompt_http_password">"Contrasinal HTTP"</string>
<string name="action_sign_in">"Ir"</string>
<string name="error_invalid_password">"O contrasinal non é suficientemente longo"</string>
<string name="error_field_required">"Campo requirido"</string>
<string name="prompt_url">"URL"</string>
<string name="withLoginSwitch">"É preciso iniciar sesión?"</string>
<string name="withHttpLoginSwitch">"É preciso iniciar sesión?"</string>
<string name="login_url_problem">"Ups! Pode que precises engadir un \"/\" o final da URL."</string>
<string name="prompt_login">"Nome de usuario"</string>
<string name="prompt_http_login">"Nome de usuario HTTP"</string>
<string name="label_share">"Compartir"</string>
<string name="readAll">"Ler todos"</string>
<string name="action_disconnect">"Desconectar"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Comprobar os teus detalles de novo."</string>
<string name="all_posts_not_read">"Non se leron todas as publicacións"</string>
<string name="all_posts_read">"Leronse todas as publicacións"</string>
<string name="cant_get_favs">"Non se poden obter os favoritos"</string>
<string name="cant_get_new_elements">"Non se poden recibir os novos artigos"</string>
<string name="cant_get_read">"Non se poden recibir os artigos lidos"</string>
<string name="nothing_here">"Non hai nada aquí"</string>
<string name="tab_new">"Novo"</string>
<string name="tab_read">"Todos"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Informar dun erro ou pedir unha nova característica"</string>
<string name="warning_wrong_url">"AVISO"</string>
<string name="pref_switch_card_view_title">"Vista de tarxeta"</string>
<string name="cant_mark_favortie">"Non se pode marcar o artigo como favorito"</string>
<string name="cant_unmark_favortie">"Non se pode eliminar o elemento dos favoritos"</string>
<string name="share">"Compartir"</string>
<string name="rating_prompt_title">"Estás gozando coa aplicación?"</string>
<string name="rating_prompt_yes">"Si !"</string>
<string name="rating_prompt_no">"Non moito …"</string>
<string name="rating_prompt_feedback_title">"Podes dicirnos por qué?"</string>
<string name="rating_prompt_feedback_yes">"Dacordo!"</string>
<string name="rating_prompt_feedback_no">"Agora non."</string>
<string name="rating_prompt_rating_title">"Xenial! Podes puntuarnos na tenda?"</string>
<string name="rating_prompt_rating_yes">"Claro!"</string>
<string name="rating_prompt_rating_no">"Agora mesmo non."</string>
<string name="rating_prompt_thanks">"Grazas, a túa opinión axudanos a mellorar a aplicación!"</string>
<string name="switch_unread_count">"Mostrar o reconto de artigos non lidos cunha insignia na barra inferior."</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>
@ -83,17 +65,12 @@
<string name="card_height_on">A altura das tarxetas axustarase ao seu contido</string>
<string name="card_height_off">A altura das tarxetas será fixa</string>
<string name="source_code">Código fonte</string>
<string name="cant_mark_read">Non se pode marcar o artigo como lido</string>
<string name="cant_mark_unread">Non se pode marcar o artigo como non lido</string>
<string name="drawer_error_loading_tags">Produciuse un erro ao cargar as etiquetas…</string>
<string name="drawer_error_loading_sources">Produciuse un erro ao cargar as fontes…</string>
<string name="drawer_item_filters">Filtros</string>
<string name="drawer_action_clear">limpar</string>
<string name="drawer_item_tags">Etiquetas</string>
<string name="drawer_item_sources">Fontes</string>
<string name="drawer_action_edit">editar</string>
<string name="no_tags_loaded">Non se cargou ningunha etiqueta</string>
<string name="no_sources_loaded">Non se cargou ningunha fonte</string>
<string name="drawer_loading">Cargando…</string>
<string name="menu_home_search">Procurar</string>
<string name="can_delete_source">Non se puido eliminar a fonte…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Temas</string>
<string name="default_theme">Predeterminado</string>
<string name="default_dark_theme">Predeterminado/Escuro</string>
<string name="pref_header_debug">Depuración</string>
<string name="self_hosted_cert_switch">Utilizas un certificado autoaloxado?</string>
<string name="self_signed_cert_warning">Por razóns de seguridade, por defecto non se permiten os certificados autoasinados. Activando isto, non serei responsable de calquera problema de seguridade que atopes.</string>
<string name="pref_selfoss_category">API de Selfoss</string>
<string name="pref_api_items_number_title">Número de elementos cargados</string>
<string name="pref_hidden_tags">Etiquetas ocultas</string>
<string name="summary_debug_identifier">Identificador de depuración</string>
<string name="unique_id_to_clipboard">Copiouse o identificador ao portapapeis</string>
<string name="display_header_drawer_summary">Amosar unha cabeceira coa URL da instancia de Selfoss no panel lateral.</string>
<string name="display_header_drawer_title">Cabeceira da conta</string>
<string name="pref_general_infinite_loading_title">Cargar máis artigos ao desprazarse</string>
<string name="translation">Traducción</string>
<string name="cant_open_invalid_url">A URL do elemento non é válida. Estou tratando de solucionar isto pra que a aplicación non falle.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Compartir</string>
<string name="pref_switch_actions_pager_scroll_on">Marcar artigos como lidos cando se desliza o dedo dun a outro.</string>
<string name="add_to_favs_reader">Engadir a favoritos</string>
<string name="remove_to_favs_reader">Eliminar dos favoritos</string>
<string name="pref_content_reader_font_size">Tamaño da fonte do lector</string>
<string name="pref_header_viewer">Visor de artigos</string>
<string name="refresh_dialog_message">Isto actualizará a súa instancia de Selfoss.</string>
<string name="markall_dialog_message">Isto marcara todos os elementos como lidos.</string>
<string name="pref_switch_actions_pager_scroll">Marcar artigos como lidos ao deslizar co dedo cara os lados</string>
<string name="pref_switch_actions_pager_scroll_off">Non marcar artigos como lidos ao deslizar co dedo cara os lados.</string>
<string name="pref_acra_alwaysaccept">Enviar automáticamente informes de erros</string>
<string name="pref_acra_alwaysaccept_enabled">Enviaranse automáticamente os informes de erros</string>
<string name="pref_acra_alwaysaccept_disabled">Preguntarase cada vez pra enviar os informes de erros.</string>
<string name="pref_debug_crash_reports">Informes de erros</string>
<string name="pref_debug_debug_logs">Rexistro de depuración (Estes enviaranse automáticamente)</string>
<string name="acra_login">Habilitar o rexistro</string>
<string name="drawer_item_hidden_tags">Etiquetas ocultas</string>
<string name="unmark">Marcar artículo como non lido</string>
<string name="pref_header_offline">Sen conexión e caché</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Gardar elementos para uso sen conexión</string>
<string name="pref_switch_update_sources">Comproba novas fontes e etiquetas</string>
<string name="pref_switch_update_sources_summary">Deshabilita isto se o teu servidor está recibindo demasiadas peticións de base de datos.</string>
<string name="no_network_connectivity">Non conectado!</string>
<string name="network_connectivity_lost">"Perdeuse a conexión de rede"</string>
<string name="network_connectivity_retrieved">"Conexión de rede xa dispoñíbel"</string>
<string name="pref_switch_periodic_refresh">Sincronizar artigos</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Reader for Selfoss"</string>
<string name="title_activity_login">"Masuk"</string>
<string name="prompt_password">"Kata sandi"</string>
<string name="prompt_http_password">"Kata sandi HTTP"</string>
<string name="action_sign_in">"Mulai"</string>
<string name="error_invalid_password">"Kata sandinya tidak cukup panjang"</string>
<string name="error_field_required">"Kolom wajib diisi"</string>
<string name="prompt_url">"URL"</string>
<string name="withLoginSwitch">"Harus masuk?"</string>
<string name="withHttpLoginSwitch">"Otentikasi HTTP diperlukan?"</string>
<string name="login_url_problem">"Ups. Anda mungkin harus menambahkan \"/\" di akhir url."</string>
<string name="prompt_login">"Nama pengguna"</string>
<string name="prompt_http_login">"Nama pengguna HTTP"</string>
<string name="label_share">"Bagikan"</string>
<string name="readAll">"Baca semua"</string>
<string name="action_disconnect">"Putuskan sambungan"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Periksa kembali detail Anda."</string>
<string name="all_posts_not_read">"Semua pos belum dibaca"</string>
<string name="all_posts_read">"Semua pos sudah dibaca"</string>
<string name="cant_get_favs">"Gagal menuju favorit"</string>
<string name="cant_get_new_elements">"Gagal ke artikel baru"</string>
<string name="cant_get_read">"Gagal ke artikel yang dibaca"</string>
<string name="nothing_here">"Tidak ada di sini"</string>
<string name="tab_new">"Baru"</string>
<string name="tab_read">"Semua"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Laporkan bug atau meminta fitur baru"</string>
<string name="warning_wrong_url">"PERINGATAN"</string>
<string name="pref_switch_card_view_title">"Tampilan Kartu"</string>
<string name="cant_mark_favortie">"Tidak dapat menandai artikel sebagai favorit"</string>
<string name="cant_unmark_favortie">"Tidak dapat melepas item dari favorit"</string>
<string name="share">"Bagikan"</string>
<string name="rating_prompt_title">"Suka aplikasi ini?"</string>
<string name="rating_prompt_yes">"Ya !"</string>
<string name="rating_prompt_no">"Tidak suka …"</string>
<string name="rating_prompt_feedback_title">"Bisakah Anda memberitahu kami alasannya?"</string>
<string name="rating_prompt_feedback_yes">"Oke !"</string>
<string name="rating_prompt_feedback_no">"Tidak sekarang."</string>
<string name="rating_prompt_rating_title">"Bagus! Dapatkah Anda memberi nilai kami di Store ?"</string>
<string name="rating_prompt_rating_yes">"Tentu saja !"</string>
<string name="rating_prompt_rating_no">"Jangan sekarang."</string>
<string name="rating_prompt_thanks">"Terima kasih, umpan balik Anda membantu pengembangan aplikasi !"</string>
<string name="switch_unread_count">"Tampilkan jumlah item yang belum dibaca di bilah bawah."</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>
@ -83,17 +65,12 @@
<string name="card_height_on">Tinggi kartu akan disesuaikan dengan konten</string>
<string name="card_height_off">Ukuran kartu akan tetap</string>
<string name="source_code">Kode sumber</string>
<string name="cant_mark_read">Tidak dapat menandai artikel sebagai telah dibaca</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Kesalahan saat memuat tag…</string>
<string name="drawer_error_loading_sources">Kesalahan saat memuat sumber…</string>
<string name="drawer_item_filters">Filter</string>
<string name="drawer_action_clear">kosongkan</string>
<string name="drawer_item_tags">Tag</string>
<string name="drawer_item_sources">Sumber</string>
<string name="drawer_action_edit">suntung</string>
<string name="no_tags_loaded">Tidak ada tag yang dimuat</string>
<string name="no_sources_loaded">Tak ada sumber yang dimuat</string>
<string name="drawer_loading">Memuat …</string>
<string name="menu_home_search">Cari</string>
<string name="can_delete_source">Tidak dapat menghapus sumber…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Tema</string>
<string name="default_theme">Bawaan</string>
<string name="default_dark_theme">Bawaan/Gelap</string>
<string name="pref_header_debug">Debug</string>
<string name="self_hosted_cert_switch">Sertifikat yang ditandatangani sendiri?</string>
<string name="self_signed_cert_warning">Untuk alasan keamanan, sertifikat yang ditandatangani sendiri tidak didukung secara bawaan. Jika Anda mengaktifkan item ini, saya tidak akan bertanggung jawab atas masalah keamanan yang Anda hadapi.</string>
<string name="pref_selfoss_category">Selfoss Api</string>
<string name="pref_api_items_number_title">Item nomor dimuat</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">Identifikasi debug</string>
<string name="unique_id_to_clipboard">Salin pengenal ke papan klip Anda</string>
<string name="display_header_drawer_summary">Kop dengan alamat link Selfoss ditampilkan di laci lateral.</string>
<string name="display_header_drawer_title">Kop akun</string>
<string name="pref_general_infinite_loading_title">Muat lebih banyak artikel saat membalik halaman</string>
<string name="translation">Terjemahan</string>
<string name="cant_open_invalid_url">Alamat tautan proyek tidak valid. Saya mencoba memecahkan masalah ini untuk menghindari aplikasi berhenti.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Bagikan</string>
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="add_to_favs_reader">Add to favorites</string>
<string name="remove_to_favs_reader">Remove from favorites</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Enable logging</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Mark item as unread</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Lettore RSS per Selfoss"</string>
<string name="title_activity_login">"Accedi"</string>
<string name="prompt_password">"Password"</string>
<string name="prompt_http_password">"Password HTTP"</string>
<string name="action_sign_in">"Vai"</string>
<string name="error_invalid_password">"La password non è sufficientemente lunga"</string>
<string name="error_field_required">"Campo obbligatorio"</string>
<string name="prompt_url">"URL"</string>
<string name="withLoginSwitch">"È richiesto l'accesso?"</string>
<string name="withHttpLoginSwitch">"Accesso HTTP necessario?"</string>
<string name="login_url_problem">"Oops. Potrebbe essere necessario aggiungere un \"/\" alla fine dell'url."</string>
<string name="prompt_login">"Nome utente"</string>
<string name="prompt_http_login">"Nome utente HTTP"</string>
<string name="label_share">"Condividi"</string>
<string name="readAll">"Segna tutte come lette"</string>
<string name="action_disconnect">"Scollegati"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Controlla nuovamente i dati."</string>
<string name="all_posts_not_read">"All posts weren't read"</string>
<string name="all_posts_read">"Tutti i messaggi sono stati letti"</string>
<string name="cant_get_favs">"Non è possibile ottenere i preferiti"</string>
<string name="cant_get_new_elements">"Non è possibile ottenere nuovi articoli"</string>
<string name="cant_get_read">"Can't get read articles"</string>
<string name="nothing_here">"Non c'è niente qui"</string>
<string name="tab_new">"Nuovi"</string>
<string name="tab_read">"Tutti"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Segnalare un bug o richiedere una nuova funzionalità"</string>
<string name="warning_wrong_url">"ATTENZIONE"</string>
<string name="pref_switch_card_view_title">"Visualizzazione a schede"</string>
<string name="cant_mark_favortie">"Can't mark article as favorite"</string>
<string name="cant_unmark_favortie">"Can't remove item from favorite"</string>
<string name="share">"Share"</string>
<string name="rating_prompt_title">"Enjoying the app ?"</string>
<string name="rating_prompt_yes">"Yes !"</string>
<string name="rating_prompt_no">"Not really …"</string>
<string name="rating_prompt_feedback_title">"Can you tell us why ?"</string>
<string name="rating_prompt_feedback_yes">"OK !"</string>
<string name="rating_prompt_feedback_no">"Not now."</string>
<string name="rating_prompt_rating_title">"Great ! Can you rate us on the Store ?"</string>
<string name="rating_prompt_rating_yes">"Sure !"</string>
<string name="rating_prompt_rating_no">"Not right now."</string>
<string name="rating_prompt_thanks">"Thanks, your feedback help enhance the app !"</string>
<string name="switch_unread_count">"Display the unread count as a badge for the bottom bar."</string>
<string name="switch_unread_count_title">"Display unread count"</string>
<string name="display_all_counts_title">"Display count for favorite and read"</string>
@ -83,17 +65,12 @@
<string name="card_height_on">Cards height will adjust to its content</string>
<string name="card_height_off">Card height will be fixed</string>
<string name="source_code">Codice sorgente</string>
<string name="cant_mark_read">Impossibile contrassegnare l\'articolo come già letto</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Errore nel caricamento dei tag…</string>
<string name="drawer_error_loading_sources">Errore nel caricamento delle fonti…</string>
<string name="drawer_item_filters">Filtri</string>
<string name="drawer_action_clear">cancella</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Fonti</string>
<string name="drawer_action_edit">modifica</string>
<string name="no_tags_loaded">Nessun tag caricato</string>
<string name="no_sources_loaded">No sources loaded</string>
<string name="drawer_loading">Caricamento…</string>
<string name="menu_home_search">Cerca</string>
<string name="can_delete_source">Non è possibile eliminare la fonte…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Temi</string>
<string name="default_theme">Predefinito</string>
<string name="default_dark_theme">Predefinito (Scuro)</string>
<string name="pref_header_debug">Debug</string>
<string name="self_hosted_cert_switch">Using a self hosted certificate ?</string>
<string name="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
<string name="pref_selfoss_category">Api di Selfoss</string>
<string name="pref_api_items_number_title">Numero di elementi caricati</string>
<string name="pref_hidden_tags">Tag nascosti</string>
<string name="summary_debug_identifier">Debug identifier</string>
<string name="unique_id_to_clipboard">Identifier copied to your clipboard</string>
<string name="display_header_drawer_summary">Display a header with the selfoss instance url on the lateral drawer.</string>
<string name="display_header_drawer_title">Account header</string>
<string name="pref_general_infinite_loading_title">Load more articles on scroll</string>
<string name="translation">Traduzioni</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="add_to_favs_reader">Add to favorites</string>
<string name="remove_to_favs_reader">Remove from favorites</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Enable logging</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Segna come non letto</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Reader for Selfoss"</string>
<string name="title_activity_login">"로그인"</string>
<string name="prompt_password">"비밀번호"</string>
<string name="prompt_http_password">"HTTP 암호"</string>
<string name="action_sign_in">"Go"</string>
<string name="error_invalid_password">"패스워드가 짧습니다."</string>
<string name="error_field_required">"필수 항목"</string>
<string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"로그인이 필요합니까?"</string>
<string name="withHttpLoginSwitch">"HTTP 로그인이 필요 합니까?"</string>
<string name="login_url_problem">"죄송합니다. Url의 끝에 \"/\"를 추가할 필요가 있습니다."</string>
<string name="prompt_login">"사용자 이름"</string>
<string name="prompt_http_login">"HTTP 사용자 이름"</string>
<string name="label_share">"공유"</string>
<string name="readAll">"모두 읽기"</string>
<string name="action_disconnect">"연결 해제"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"세부 정보를 다시 확인하세요."</string>
<string name="all_posts_not_read">"모든 게시물을 읽지 않았습니다."</string>
<string name="all_posts_read">"모든 게시물을 읽었습니다."</string>
<string name="cant_get_favs">"즐겨찾기를 가져올 수 없습니다."</string>
<string name="cant_get_new_elements">"새로운 기사를 가져올 수 없습니다."</string>
<string name="cant_get_read">"읽은 기사를 가져올 수 없습니다."</string>
<string name="nothing_here">"비어있음"</string>
<string name="tab_new">"새로운"</string>
<string name="tab_read">"전체"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"버그를 보고 하거나 새기능에 대해 요청하세요."</string>
<string name="warning_wrong_url">"경고"</string>
<string name="pref_switch_card_view_title">"카드 형식 보기"</string>
<string name="cant_mark_favortie">"좋아하는 문서를 마크할 수 없습니다."</string>
<string name="cant_unmark_favortie">"좋아하는 항목에서 제거할 수 없습니다."</string>
<string name="share">"공유"</string>
<string name="rating_prompt_title">"이 앱에 만족하십니까?"</string>
<string name="rating_prompt_yes">"예!"</string>
<string name="rating_prompt_no">"설마..."</string>
<string name="rating_prompt_feedback_title">"이유를 우리에게 말해줄 수 있습니까?"</string>
<string name="rating_prompt_feedback_yes">"OK!"</string>
<string name="rating_prompt_feedback_no">"나중에"</string>
<string name="rating_prompt_rating_title">"Great ! Can you rate us on the Store ?"</string>
<string name="rating_prompt_rating_yes">"Sure !"</string>
<string name="rating_prompt_rating_no">"Not right now."</string>
<string name="rating_prompt_thanks">"Thanks, your feedback help enhance the app !"</string>
<string name="switch_unread_count">"Display the unread count as a badge for the bottom bar."</string>
<string name="switch_unread_count_title">"Display unread count"</string>
<string name="display_all_counts_title">"Display count for favorite and read"</string>
@ -83,17 +65,12 @@
<string name="card_height_on">Cards height will adjust to its content</string>
<string name="card_height_off">Card height will be fixed</string>
<string name="source_code">Source code</string>
<string name="cant_mark_read">Can\'t mark article as read</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Error loading tags…</string>
<string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="drawer_item_filters">Filters</string>
<string name="drawer_action_clear">clear</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Sources</string>
<string name="drawer_action_edit">edit</string>
<string name="no_tags_loaded">No tags loaded</string>
<string name="no_sources_loaded">No sources loaded</string>
<string name="drawer_loading">Loading …</string>
<string name="menu_home_search">Search</string>
<string name="can_delete_source">Can\'t delete the source…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Themes</string>
<string name="default_theme">Default</string>
<string name="default_dark_theme">Default/Dark</string>
<string name="pref_header_debug">Debug</string>
<string name="self_hosted_cert_switch">Using a self hosted certificate ?</string>
<string name="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
<string name="pref_selfoss_category">Selfoss Api</string>
<string name="pref_api_items_number_title">Loaded items number</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">Debug identifier</string>
<string name="unique_id_to_clipboard">Identifier copied to your clipboard</string>
<string name="display_header_drawer_summary">Display a header with the selfoss instance url on the lateral drawer.</string>
<string name="display_header_drawer_title">Account header</string>
<string name="pref_general_infinite_loading_title">Load more articles on scroll</string>
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="add_to_favs_reader">Add to favorites</string>
<string name="remove_to_favs_reader">Remove from favorites</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Enable logging</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Mark item as unread</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Selfoss Reader"</string>
<string name="title_activity_login">"Inloggen"</string>
<string name="prompt_password">"Wachtwoord"</string>
<string name="prompt_http_password">"HTTP Wachtwoord"</string>
<string name="action_sign_in">"Inloggen"</string>
<string name="error_invalid_password">"Wachtwoord niet lang genoeg"</string>
<string name="error_field_required">"Dit veld is verplicht"</string>
<string name="prompt_url">"Selfoss server"</string>
<string name="withLoginSwitch">"Authenticatie vereist?"</string>
<string name="withHttpLoginSwitch">"HTTP Authenticatie vereist?"</string>
<string name="login_url_problem">"Oeps, ben je soms de \"/\" vergeten aan het eind?"</string>
<string name="prompt_login">"Gebruikersnaam"</string>
<string name="prompt_http_login">"HTTP Gebruikersnaam"</string>
<string name="label_share">"Delen"</string>
<string name="readAll">"Alles lezen"</string>
<string name="action_disconnect">"Verbinding verbreken"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Controleer de gegevens nogmaals."</string>
<string name="all_posts_not_read">"Fout bij markeren als gelezen"</string>
<string name="all_posts_read">"Alle artikelen gemarkeerd als gelezen"</string>
<string name="cant_get_favs">"Ophalen favorieten mislukt"</string>
<string name="cant_get_new_elements">"Ophalen nieuwe artikelen mislukt"</string>
<string name="cant_get_read">"Ophalen reeds gelezen artikelen mislukt"</string>
<string name="nothing_here">"Niets gevonden"</string>
<string name="tab_new">"Nieuw"</string>
<string name="tab_read">"Alle"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Rapporteer een probleem of dien een verzoek in"</string>
<string name="warning_wrong_url">"WAARSCHUWING"</string>
<string name="pref_switch_card_view_title">"Kaart weergave"</string>
<string name="cant_mark_favortie">"Kan het artikel niet markeren als favoriet"</string>
<string name="cant_unmark_favortie">"Kan het item niet verwijderen uit favorieten"</string>
<string name="share">"Delen"</string>
<string name="rating_prompt_title">"Bevalt deze app?"</string>
<string name="rating_prompt_yes">"Ja!"</string>
<string name="rating_prompt_no">"Niet echt…"</string>
<string name="rating_prompt_feedback_title">"Kun je ons vertellen waarom?"</string>
<string name="rating_prompt_feedback_yes">"OK!"</string>
<string name="rating_prompt_feedback_no">"Niet nu."</string>
<string name="rating_prompt_rating_title">"Fantastisch! Wil je een review achter laten in de Store?"</string>
<string name="rating_prompt_rating_yes">"Vanzelfsprekend"</string>
<string name="rating_prompt_rating_no">"Niet op dit moment"</string>
<string name="rating_prompt_thanks">"Bedankt, jouw feedback helpt ons de app te verbeteren"</string>
<string name="switch_unread_count">"Geef het aantal ongelezen artikelen weer in de balk onderaan"</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>
@ -83,17 +65,12 @@
<string name="card_height_on">Hoogte aanpassen aan de hand van kaartinhoud</string>
<string name="card_height_off">Vaste hoogte</string>
<string name="source_code">Broncode</string>
<string name="cant_mark_read">Impossible de marquer l\'article comme lu</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Fout bij het laden van tags…</string>
<string name="drawer_error_loading_sources">Fout bij laden van bronnen…</string>
<string name="drawer_item_filters">Filters</string>
<string name="drawer_action_clear">wissen</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Bronnen</string>
<string name="drawer_action_edit">bewerken</string>
<string name="no_tags_loaded">Geen tags geladen</string>
<string name="no_sources_loaded">Geen bronnen geladen</string>
<string name="drawer_loading">Bezig met laden …</string>
<string name="menu_home_search">Zoeken</string>
<string name="can_delete_source">Kan de bron niet verwijderen…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Thema \'s</string>
<string name="default_theme">Standaard</string>
<string name="default_dark_theme">Standaard/Donker</string>
<string name="pref_header_debug">Fout opsporen</string>
<string name="self_hosted_cert_switch">Gebruik een zelf gehost certificaat?</string>
<string name="self_signed_cert_warning">Vanwege veiligheidsredenen worden zelfondertekende certificaten niet standaard ondersteund. Door dit te activeren, ben ik niet verantwoordelijk voor beveiligingsproblemen die u tegenkomt.</string>
<string name="pref_selfoss_category">Selfoss Api</string>
<string name="pref_api_items_number_title">Geladen items nummer</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">ID voor foutopsporing</string>
<string name="unique_id_to_clipboard">ID naar uw klembord gekopieerd</string>
<string name="display_header_drawer_summary">Laat een koptekst weergeven met de url van de selfoss instantie in de zijlade.</string>
<string name="display_header_drawer_title">Account titel</string>
<string name="pref_general_infinite_loading_title">Laad meer artikelen door te bladeren</string>
<string name="translation">Vertaling</string>
<string name="cant_open_invalid_url">De URL is ongeldig. Ik probeer dit probleem op te lossen, zodat de toepassing niet wordt afgesloten.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Delen</string>
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="add_to_favs_reader">Add to favorites</string>
<string name="remove_to_favs_reader">Remove from favorites</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Enable logging</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Mark item as unread</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Reader for Selfoss"</string>
<string name="title_activity_login">"Entrar"</string>
<string name="prompt_password">"Senha"</string>
<string name="prompt_http_password">"Senha HTTP"</string>
<string name="action_sign_in">"Vamos lá"</string>
<string name="error_invalid_password">"Senha muito pequena"</string>
<string name="error_field_required">"Campo obrigatório"</string>
<string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"É necessário o login ?"</string>
<string name="withHttpLoginSwitch">"É necessário o login HTTP ?"</string>
<string name="login_url_problem">"Oops. Talvez você precise adicionar uma \"/\" no final da url."</string>
<string name="prompt_login">"Usuário"</string>
<string name="prompt_http_login">"Usuário HTTP"</string>
<string name="label_share">"Compartilhar"</string>
<string name="readAll">"Ler todos"</string>
<string name="action_disconnect">"Desconectar"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Verifique os detalhes novamente."</string>
<string name="all_posts_not_read">"Nenhum post foi lido"</string>
<string name="all_posts_read">"Todos os posts foram lidos"</string>
<string name="cant_get_favs">"Não consigo obter os favoritos"</string>
<string name="cant_get_new_elements">"Não consigo obter novos artigos"</string>
<string name="cant_get_read">"Não consigo ler artigos"</string>
<string name="nothing_here">"Nada aqui"</string>
<string name="tab_new">"Novo"</string>
<string name="tab_read">"Todos"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Informe um erro ou peça um novo recurso"</string>
<string name="warning_wrong_url">"ATENÇÃO"</string>
<string name="pref_switch_card_view_title">"Card View"</string>
<string name="cant_mark_favortie">"Não é possível marcar o artigo como favorito"</string>
<string name="cant_unmark_favortie">"Não é possível remover o item do favorito"</string>
<string name="share">"Compartilhar"</string>
<string name="rating_prompt_title">"Aproveitando o app ?"</string>
<string name="rating_prompt_yes">"Sim !"</string>
<string name="rating_prompt_no">"Na verdade não …"</string>
<string name="rating_prompt_feedback_title">"Você pode nos dizer o porquê ?"</string>
<string name="rating_prompt_feedback_yes">"OK !"</string>
<string name="rating_prompt_feedback_no">"Não agora."</string>
<string name="rating_prompt_rating_title">"Ótimo ! Você pode nos avaliar na loja ?"</string>
<string name="rating_prompt_rating_yes">"Com certeza !"</string>
<string name="rating_prompt_rating_no">"Não agora."</string>
<string name="rating_prompt_thanks">"Obrigado, seu comentário ajuda a melhorar o app !"</string>
<string name="switch_unread_count">"Exibir a contagem de artigos não lidos como um badge na barra inferior."</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>
@ -83,17 +65,12 @@
<string name="card_height_on">Cards com altura ajustáveis de acordo com o conteúdo</string>
<string name="card_height_off">Cards com altura de tamanho fixo</string>
<string name="source_code">Código fonte</string>
<string name="cant_mark_read">Não é possível marcar o artigo como lido</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Erro ao carregar as tags…</string>
<string name="drawer_error_loading_sources">Erro ao carregar as fontes…</string>
<string name="drawer_item_filters">Filtros</string>
<string name="drawer_action_clear">limpar</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Fontes</string>
<string name="drawer_action_edit">editar</string>
<string name="no_tags_loaded">Nenhuma tag carregada</string>
<string name="no_sources_loaded">Nenhuma fonte carregada</string>
<string name="drawer_loading">Carregando …</string>
<string name="menu_home_search">Procurar</string>
<string name="can_delete_source">Não foi possível apagar a fonte…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Temas</string>
<string name="default_theme">Padrão</string>
<string name="default_dark_theme">Padrão/Escuro</string>
<string name="pref_header_debug">Depurar</string>
<string name="self_hosted_cert_switch">Usando um certificado autônomo ?</string>
<string name="self_signed_cert_warning">Por motivos de segurança, certificados autônomos não são suportados por padrão. Ao ativar, não serei responsável por qualquer problema de segurança que você encontre.</string>
<string name="pref_selfoss_category">Selfoss Api</string>
<string name="pref_api_items_number_title">Quantidade de itens carregados</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">Identificador de depuração</string>
<string name="unique_id_to_clipboard">Identificador copiado para a área de transferência</string>
<string name="display_header_drawer_summary">Exibir um cabeçalho com o URL da instância do Selfoss na barra lateral.</string>
<string name="display_header_drawer_title">Cabeçalho da conta</string>
<string name="pref_general_infinite_loading_title">Carregar mais artigos ao realizar o scroll</string>
<string name="translation">Traduções</string>
<string name="cant_open_invalid_url">A url está inválida. Estou tentando resolver esse problema para que o aplicativo não encerre.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Compartilhar</string>
<string name="pref_switch_actions_pager_scroll_on">Se esta configuração estiver ativada, os artigos serão marcados como lidos ao deslizar para a esquerda e para a direita no leitor do artigo.</string>
<string name="add_to_favs_reader">Adicionar aos favoritos</string>
<string name="remove_to_favs_reader">Remover dos favoritos</string>
<string name="pref_content_reader_font_size">Tamanho da fonte do conteúdo do leitor de artigos</string>
<string name="pref_header_viewer">Visualizador de artigos</string>
<string name="refresh_dialog_message">Isso atualizará sua instância do Selfoss.</string>
<string name="markall_dialog_message">Isso marcará todos os itens como lidos.</string>
<string name="pref_switch_actions_pager_scroll">Marcar Como Lida ao Abrir</string>
<string name="pref_switch_actions_pager_scroll_off">Não marca artigos como lido quando abrir.</string>
<string name="pref_acra_alwaysaccept">Envia relatórios de erros automaticamente</string>
<string name="pref_acra_alwaysaccept_enabled">Enviar relatórios de erro automaticamente</string>
<string name="pref_acra_alwaysaccept_disabled">Perguntar sempre, ao enviar relatórios de erro.</string>
<string name="pref_debug_crash_reports">Relatório de erro</string>
<string name="pref_debug_debug_logs">Log de depuração (Serão enviados sem uma caixa de diálogo)</string>
<string name="acra_login">Ativar registro de erros</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Mark item as unread</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Leitor para Selfoss"</string>
<string name="title_activity_login">"Iniciar sessão"</string>
<string name="prompt_password">"Palavra passe"</string>
<string name="prompt_http_password">"Senha HTTP"</string>
<string name="action_sign_in">"Ir"</string>
<string name="error_invalid_password">"Senha não é longa o suficiente"</string>
<string name="error_field_required">"Campo obrigatório"</string>
<string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"É necessário fazer login?"</string>
<string name="withHttpLoginSwitch">"É necessário fazer login on HTTP?"</string>
<string name="login_url_problem">"Uups. Você pode precisar adicionar uma \"/\" no final da url."</string>
<string name="prompt_login">"Nome do usuário"</string>
<string name="prompt_http_login">"Nome de utilizador HTTP"</string>
<string name="label_share">"Compartilhar"</string>
<string name="readAll">"Ler tudo"</string>
<string name="action_disconnect">"Desligar"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Verifique seus dados novamente."</string>
<string name="all_posts_not_read">"Todas as postagens não foram lidas"</string>
<string name="all_posts_read">"Todas as postagens foram lidas"</string>
<string name="cant_get_favs">"Não é possível obter favoritos"</string>
<string name="cant_get_new_elements">"Não é possível obter novos artigos"</string>
<string name="cant_get_read">"Não é possível ler artigos"</string>
<string name="nothing_here">"Nada aqui"</string>
<string name="tab_new">"Novo"</string>
<string name="tab_read">"Tudo"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Relatar um bug ou pedir um novo recurso"</string>
<string name="warning_wrong_url">"AVISO"</string>
<string name="pref_switch_card_view_title">"Vista de cartão"</string>
<string name="cant_mark_favortie">"Não é possível marcar o artigo como favorito"</string>
<string name="cant_unmark_favortie">"Não pode remover o item do favorito"</string>
<string name="share">"Compartilhar"</string>
<string name="rating_prompt_title">"Gosta da aplicação?"</string>
<string name="rating_prompt_yes">"Sim!"</string>
<string name="rating_prompt_no">"Não realmente…"</string>
<string name="rating_prompt_feedback_title">"Pode nos dizer por que?"</string>
<string name="rating_prompt_feedback_yes">"Okey!"</string>
<string name="rating_prompt_feedback_no">"Agora não."</string>
<string name="rating_prompt_rating_title">"Legal! Você pode classificar-na loja?"</string>
<string name="rating_prompt_rating_yes">"Claro!"</string>
<string name="rating_prompt_rating_no">"Agora não."</string>
<string name="rating_prompt_thanks">"Obrigado, seu feedback ajudar a realçar o app!"</string>
<string name="switch_unread_count">"Exibir a contagem não lida como um emblema para a barra inferior."</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>
@ -83,17 +65,12 @@
<string name="card_height_on">Altura de cartas irá ajustar ao seu conteúdo</string>
<string name="card_height_off">Altura do cartão será corrigida</string>
<string name="source_code">Código fonte</string>
<string name="cant_mark_read">Não pode marcar o artigo como lido</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Erro ao carregar etiquetas…</string>
<string name="drawer_error_loading_sources">Erro ao carregar fontes…</string>
<string name="drawer_item_filters">Filtros</string>
<string name="drawer_action_clear">limpar</string>
<string name="drawer_item_tags">Etiquetas</string>
<string name="drawer_item_sources">Fontes</string>
<string name="drawer_action_edit">editar</string>
<string name="no_tags_loaded">Não tags carregado</string>
<string name="no_sources_loaded">Não há fontes carregadas</string>
<string name="drawer_loading">A carregar…</string>
<string name="menu_home_search">Buscar</string>
<string name="can_delete_source">Não é possível excluir a fonte…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Temas</string>
<string name="default_theme">Predefinição</string>
<string name="default_dark_theme">Padrão/escuro</string>
<string name="pref_header_debug">Depurar</string>
<string name="self_hosted_cert_switch">Usando um certificado hospedado?</string>
<string name="self_signed_cert_warning">Devido a razões de segurança, auto certificados auto-assinados não são suportados por padrão. Ao activar isto, eu não vou ser responsável de qualquer problema de segurança que você encontrar.</string>
<string name="pref_selfoss_category">Api de Selfoss</string>
<string name="pref_api_items_number_title">Número de itens carregados</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">Depurar o identificador</string>
<string name="unique_id_to_clipboard">Identificador de copiados para a área de transferência</string>
<string name="display_header_drawer_summary">Exibir um cabeçalho com o url de instância de selfoss na gaveta lateral.</string>
<string name="display_header_drawer_title">Cabeçalho de conta</string>
<string name="pref_general_infinite_loading_title">Carregar mais artigos no pergaminho</string>
<string name="translation">Tradução</string>
<string name="cant_open_invalid_url">A url do item é inválido. Eu estou olhando para resolver esta questão, para que o app não vai falhar.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Compartilhar</string>
<string name="pref_switch_actions_pager_scroll_on">Artigos de marca como lida quando passar entre artigos.</string>
<string name="add_to_favs_reader">Add to favorites</string>
<string name="remove_to_favs_reader">Remove from favorites</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Enable logging</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Mark item as unread</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Reader for Selfoss"</string>
<string name="title_activity_login">"පිවිසෙන්න"</string>
<string name="prompt_password">"මුර පදය"</string>
<string name="prompt_http_password">"HTTP Password"</string>
<string name="action_sign_in">"Go"</string>
<string name="error_invalid_password">"Password not long enough"</string>
<string name="error_field_required">"Field required"</string>
<string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"Login required ?"</string>
<string name="withHttpLoginSwitch">"HTTP Login required ?"</string>
<string name="login_url_problem">"Oops. You may need to add a \"/\" at the end of the url."</string>
<string name="prompt_login">"පරිශීලක නාමය"</string>
<string name="prompt_http_login">"HTTP Username"</string>
<string name="label_share">"Share"</string>
<string name="readAll">"Read all"</string>
<string name="action_disconnect">"Disconnect"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Check your details again."</string>
<string name="all_posts_not_read">"All posts weren't read"</string>
<string name="all_posts_read">"All posts were read"</string>
<string name="cant_get_favs">"Can't get favorites"</string>
<string name="cant_get_new_elements">"Can't get new articles"</string>
<string name="cant_get_read">"Can't get read articles"</string>
<string name="nothing_here">"Nothing here"</string>
<string name="tab_new">"New"</string>
<string name="tab_read">"සියල්ල"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Report a bug or ask for a new feature"</string>
<string name="warning_wrong_url">"WARNING"</string>
<string name="pref_switch_card_view_title">"Card View"</string>
<string name="cant_mark_favortie">"Can't mark article as favorite"</string>
<string name="cant_unmark_favortie">"Can't remove item from favorite"</string>
<string name="share">"Share"</string>
<string name="rating_prompt_title">"Enjoying the app ?"</string>
<string name="rating_prompt_yes">"Yes !"</string>
<string name="rating_prompt_no">"Not really …"</string>
<string name="rating_prompt_feedback_title">"Can you tell us why ?"</string>
<string name="rating_prompt_feedback_yes">"OK !"</string>
<string name="rating_prompt_feedback_no">"Not now."</string>
<string name="rating_prompt_rating_title">"Great ! Can you rate us on the Store ?"</string>
<string name="rating_prompt_rating_yes">"Sure !"</string>
<string name="rating_prompt_rating_no">"Not right now."</string>
<string name="rating_prompt_thanks">"Thanks, your feedback help enhance the app !"</string>
<string name="switch_unread_count">"Display the unread count as a badge for the bottom bar."</string>
<string name="switch_unread_count_title">"Display unread count"</string>
<string name="display_all_counts_title">"Display count for favorite and read"</string>
@ -83,17 +65,12 @@
<string name="card_height_on">Cards height will adjust to its content</string>
<string name="card_height_off">Card height will be fixed</string>
<string name="source_code">Source code</string>
<string name="cant_mark_read">Can\'t mark article as read</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Error loading tags…</string>
<string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="drawer_item_filters">Filters</string>
<string name="drawer_action_clear">clear</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Sources</string>
<string name="drawer_action_edit">edit</string>
<string name="no_tags_loaded">No tags loaded</string>
<string name="no_sources_loaded">No sources loaded</string>
<string name="drawer_loading">Loading …</string>
<string name="menu_home_search">Search</string>
<string name="can_delete_source">Can\'t delete the source…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Themes</string>
<string name="default_theme">Default</string>
<string name="default_dark_theme">Default/Dark</string>
<string name="pref_header_debug">Debug</string>
<string name="self_hosted_cert_switch">Using a self hosted certificate ?</string>
<string name="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
<string name="pref_selfoss_category">Selfoss Api</string>
<string name="pref_api_items_number_title">Loaded items number</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">Debug identifier</string>
<string name="unique_id_to_clipboard">Identifier copied to your clipboard</string>
<string name="display_header_drawer_summary">Display a header with the selfoss instance url on the lateral drawer.</string>
<string name="display_header_drawer_title">Account header</string>
<string name="pref_general_infinite_loading_title">Load more articles on scroll</string>
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="add_to_favs_reader">Add to favorites</string>
<string name="remove_to_favs_reader">Remove from favorites</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Enable logging</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Mark item as unread</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Selfoss için okuyucu"</string>
<string name="title_activity_login">"Giriş"</string>
<string name="prompt_password">"Şifre"</string>
<string name="prompt_http_password">"HTTP şifresi"</string>
<string name="action_sign_in">"Git"</string>
<string name="error_invalid_password">"Parola yeterince uzun değil"</string>
<string name="error_field_required">"Alan gereklidir"</string>
<string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"Kullanıcı Girişi Gerekli?"</string>
<string name="withHttpLoginSwitch">"HTTP üyelik gerekmektedir?"</string>
<string name="login_url_problem">"Oops. Url'nin sonuna \"/\" eklemek gerekebilir."</string>
<string name="prompt_login">"Kullanıcı adı"</string>
<string name="prompt_http_login">"HTTP kullanıcı adı"</string>
<string name="label_share">"Paylaş"</string>
<string name="readAll">"Tümünü oku"</string>
<string name="action_disconnect">"Bağlantıyı kes"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"Detaylarınızı tekrar kontrol edin."</string>
<string name="all_posts_not_read">"Tüm mesajlar okunmadı"</string>
<string name="all_posts_read">"Tüm mesajlar okundu"</string>
<string name="cant_get_favs">"Sık ullanılanlara ulaşılamıyor"</string>
<string name="cant_get_new_elements">"Yeni makalelere ulaşılamıyor"</string>
<string name="cant_get_read">"Yeni makaleler okunamıyor"</string>
<string name="nothing_here">"Burada hiçbir şey yok"</string>
<string name="tab_new">"Yeni"</string>
<string name="tab_read">"Tüm"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"Bir hatayı bildir veya yeni bir özellik iste"</string>
<string name="warning_wrong_url">"UYARI"</string>
<string name="pref_switch_card_view_title">"Kart görünümü"</string>
<string name="cant_mark_favortie">"Makale favori olarak işaretlenemez"</string>
<string name="cant_unmark_favortie">"Nesne favorilerden kaldırılamıyor"</string>
<string name="share">"Paylaş"</string>
<string name="rating_prompt_title">"Uygulamayı sevdiniz mi?"</string>
<string name="rating_prompt_yes">"Evet!"</string>
<string name="rating_prompt_no">"Aslında değil…"</string>
<string name="rating_prompt_feedback_title">"Nedenini bize söyleyebilir misiniz?"</string>
<string name="rating_prompt_feedback_yes">"Tamam!"</string>
<string name="rating_prompt_feedback_no">"Henüz değil."</string>
<string name="rating_prompt_rating_title">"Harika ! Bizi mağzada oylayabilir misin?"</string>
<string name="rating_prompt_rating_yes">"Tabii ki!"</string>
<string name="rating_prompt_rating_no">"Şimdi değil."</string>
<string name="rating_prompt_thanks">"Teşekkürler, geri dönüşünü uygulamayı geliştirmede yardımcı olur!"</string>
<string name="switch_unread_count">"Okunmamış sayıyı, alt çubuk için bir rozet olarak görüntüleyin."</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>
@ -83,17 +65,12 @@
<string name="card_height_on">Kartların yüksekliği içeriğine göre ayarlanır</string>
<string name="card_height_off">Kart yüksekliği sabit olacak</string>
<string name="source_code">Kaynak kodu</string>
<string name="cant_mark_read">Makale favori olarak işaretlenemez</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Etiketler yükleme hatası</string>
<string name="drawer_error_loading_sources">Kaynaklar yüklenirken hata oluştu…</string>
<string name="drawer_item_filters">Filtreler</string>
<string name="drawer_action_clear">temizle</string>
<string name="drawer_item_tags">Etiketler</string>
<string name="drawer_item_sources">Kaynaklar</string>
<string name="drawer_action_edit">düzenle</string>
<string name="no_tags_loaded">Yüklenen görüntü yok</string>
<string name="no_sources_loaded">Yüklenen kaynak yok</string>
<string name="drawer_loading">Yükleniyor…</string>
<string name="menu_home_search">Ara</string>
<string name="can_delete_source">Kaynak silinemiyor…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">Temalar</string>
<string name="default_theme">Varsayılan</string>
<string name="default_dark_theme">Varsayılan/koyu</string>
<string name="pref_header_debug">Hata ayıklama</string>
<string name="self_hosted_cert_switch">Kendi kendine barındırılan bir sertifika mı kullanıyorsunuz?</string>
<string name="self_signed_cert_warning">Güvenlik nedeniyle, kendinden imzalı sertifikalar varsayılan olarak desteklenmez. Bunu etkinleştirerek karşılaştığınız herhangi bir güvenlik sorununun sorumluluğunu almayacağım.</string>
<string name="pref_selfoss_category">Selfoss Uygulaması</string>
<string name="pref_api_items_number_title">Yüklenen öğe numarası</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">Hata ayıklama tanıtıcısı</string>
<string name="unique_id_to_clipboard">Tanımlayıcı panonuza kopyalanır</string>
<string name="display_header_drawer_summary">Selfoss örneği url\'li bir üstbilgi, yan çekmece üzerine gösterin.</string>
<string name="display_header_drawer_title">Hesap başlığı</string>
<string name="pref_general_infinite_loading_title">Kaydırma üzerine daha fazla makale yükleyin</string>
<string name="translation">Çeviri</string>
<string name="cant_open_invalid_url">Öğe url geçersiz. Uygulama çökmeyeceği için bu sorunu çözmeye çalışıyorum.</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">Paylaş</string>
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="add_to_favs_reader">Add to favorites</string>
<string name="remove_to_favs_reader">Remove from favorites</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Enable logging</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Mark item as unread</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Selfoss 阅读器"</string>
<string name="title_activity_login">"登录"</string>
<string name="prompt_password">"密码"</string>
<string name="prompt_http_password">"HTTP 密码"</string>
<string name="action_sign_in">"转至"</string>
<string name="error_invalid_password">"密码不够长"</string>
<string name="error_field_required">"必填字段"</string>
<string name="prompt_url">"网址"</string>
<string name="withLoginSwitch">"需要登录?"</string>
<string name="withHttpLoginSwitch">"请先登录网站"</string>
<string name="login_url_problem">"哎呀。您可能需要在网址的末尾添加一个 \"/\"。"</string>
<string name="prompt_login">"用户名"</string>
<string name="prompt_http_login">"HTTP 用户名"</string>
<string name="label_share">"分享"</string>
<string name="readAll">"全部阅读"</string>
<string name="action_disconnect">"断开连接"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"再次检查您的详细信息。"</string>
<string name="all_posts_not_read">"所有帖子都未读"</string>
<string name="all_posts_read">"所有帖子已读"</string>
<string name="cant_get_favs">"无法获取收藏文件"</string>
<string name="cant_get_new_elements">"无法获取新文章"</string>
<string name="cant_get_read">"无法获取已读文章"</string>
<string name="nothing_here">"暂无内容!"</string>
<string name="tab_new">"新建"</string>
<string name="tab_read">"所有"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"报告错误或请求新功能"</string>
<string name="warning_wrong_url">"警告"</string>
<string name="pref_switch_card_view_title">"卡片视图"</string>
<string name="cant_mark_favortie">"不能将文章标记为收藏"</string>
<string name="cant_unmark_favortie">"无法从收藏中删除项目"</string>
<string name="share">"共享"</string>
<string name="rating_prompt_title">"喜欢这个应用吗?"</string>
<string name="rating_prompt_yes">"是的!"</string>
<string name="rating_prompt_no">"不大喜欢…"</string>
<string name="rating_prompt_feedback_title">"能告诉我们为什么吗?"</string>
<string name="rating_prompt_feedback_yes">"好的!"</string>
<string name="rating_prompt_feedback_no">"以后再说。"</string>
<string name="rating_prompt_rating_title">"太好了!你能在应用商店给我们打分吗?"</string>
<string name="rating_prompt_rating_yes">"当然!"</string>
<string name="rating_prompt_rating_no">"现在不行。"</string>
<string name="rating_prompt_thanks">"谢谢,您的反馈有助于改进应用程序!"</string>
<string name="switch_unread_count">"将未读数在底部显示为一个徽标。"</string>
<string name="switch_unread_count_title">"显示未读数"</string>
<string name="display_all_counts_title">"显示收藏和已读的计数"</string>
@ -83,17 +65,12 @@
<string name="card_height_on">卡片高度将根据内容调整</string>
<string name="card_height_off">卡片高度将被固定</string>
<string name="source_code">源代码</string>
<string name="cant_mark_read">无法将文章标记为已读</string>
<string name="cant_mark_unread">无法将文章标记为未读</string>
<string name="drawer_error_loading_tags">加载标记时出错..。</string>
<string name="drawer_error_loading_sources">加载源时出错..。</string>
<string name="drawer_item_filters">搜索条件</string>
<string name="drawer_action_clear">清空</string>
<string name="drawer_item_tags">标签</string>
<string name="drawer_item_sources">来源</string>
<string name="drawer_action_edit">编辑</string>
<string name="no_tags_loaded">未加载标签</string>
<string name="no_sources_loaded">未加载数据源</string>
<string name="drawer_loading">正在载入…</string>
<string name="menu_home_search">搜索</string>
<string name="can_delete_source">无法删除数据源…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">主题</string>
<string name="default_theme">默认​​​​​</string>
<string name="default_dark_theme">默认值/暗</string>
<string name="pref_header_debug">调试</string>
<string name="self_hosted_cert_switch">使用自托管证书?</string>
<string name="self_signed_cert_warning">出于安全考虑, 默认情况下不支持自签名证书。如果激活此项, 您遇到的任何安全问题我将概不负责。</string>
<string name="pref_selfoss_category">塞尔福斯 Api</string>
<string name="pref_api_items_number_title">已加载项目编号</string>
<string name="pref_hidden_tags">隐藏标签</string>
<string name="summary_debug_identifier">除错标识符</string>
<string name="unique_id_to_clipboard">复制到你的剪贴板的标识符</string>
<string name="display_header_drawer_summary">在侧边栏中显示带有 Selfoss 链接地址的页眉。</string>
<string name="display_header_drawer_title">帐户页眉</string>
<string name="pref_general_infinite_loading_title">翻页时载入更多文章</string>
<string name="translation">翻译</string>
<string name="cant_open_invalid_url">项目链接地址无效。我正在设法解决这个问题,以避免应用程序崩溃。</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">分享</string>
<string name="pref_switch_actions_pager_scroll_on">切换文章时将文章标记为已读。</string>
<string name="add_to_favs_reader">添加到收藏</string>
<string name="remove_to_favs_reader">从收藏中移除</string>
<string name="pref_content_reader_font_size">文章阅读器内容字体大小</string>
<string name="pref_header_viewer">文章查看器</string>
<string name="refresh_dialog_message">这将刷新您的 Selfoss 实例。</string>
<string name="markall_dialog_message">这将标记所有项目为已读。</string>
<string name="pref_switch_actions_pager_scroll">滑动时标为已读</string>
<string name="pref_switch_actions_pager_scroll_off">滑动时不标记文章为已读</string>
<string name="pref_acra_alwaysaccept">自动发送崩溃报告</string>
<string name="pref_acra_alwaysaccept_enabled">允许自动发送故障报告</string>
<string name="pref_acra_alwaysaccept_disabled">每次发送崩溃报告时都会询问。</string>
<string name="pref_debug_crash_reports">崩溃报告</string>
<string name="pref_debug_debug_logs">调试日志(这些日志将在没有对话框的情况下发送)</string>
<string name="acra_login">启用日志记录</string>
<string name="drawer_item_hidden_tags">隐藏标签</string>
<string name="unmark">标记条目为未读</string>
<string name="pref_header_offline">离线和缓存</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">保存项目以便离线使用</string>
<string name="pref_switch_update_sources">检查新来源和标签</string>
<string name="pref_switch_update_sources_summary">如果你的服务器接收过多的数据库查询,请禁用此功能。</string>
<string name="no_network_connectivity">未连接!</string>
<string name="network_connectivity_lost">"网络连接丢失"</string>
<string name="network_connectivity_retrieved">"网络连接现在可用"</string>
<string name="pref_switch_periodic_refresh">同步文章</string>

View File

@ -3,16 +3,13 @@
<string name="app_name">"Selfoss 阅读器"</string>
<string name="title_activity_login">"登录"</string>
<string name="prompt_password">"密码"</string>
<string name="prompt_http_password">"HTTP 密碼"</string>
<string name="action_sign_in">"转至"</string>
<string name="error_invalid_password">"密码不够长"</string>
<string name="error_field_required">"欄位必填"</string>
<string name="prompt_url">"网址"</string>
<string name="withLoginSwitch">"需要登入?"</string>
<string name="withHttpLoginSwitch">"请先登录网站"</string>
<string name="login_url_problem">"哎呀。您可能需要在网址的末尾添加一个 \"/\"。"</string>
<string name="prompt_login">"使用者名稱"</string>
<string name="prompt_http_login">"HTTP 用户名"</string>
<string name="label_share">"分享"</string>
<string name="readAll">"全部阅读"</string>
<string name="action_disconnect">"断开连接"</string>
@ -26,9 +23,6 @@
<string name="wrong_infos">"再次检查您的详细信息。"</string>
<string name="all_posts_not_read">"所有帖子都未读"</string>
<string name="all_posts_read">"所有帖子已读"</string>
<string name="cant_get_favs">"无法获取收藏文件"</string>
<string name="cant_get_new_elements">"无法获取新文章"</string>
<string name="cant_get_read">"无法获取已读文章"</string>
<string name="nothing_here">"暂无内容!"</string>
<string name="tab_new">"新建"</string>
<string name="tab_read">"所有"</string>
@ -48,19 +42,7 @@
<string name="issue_tracker_summary">"报告错误或请求新功能"</string>
<string name="warning_wrong_url">"警告"</string>
<string name="pref_switch_card_view_title">"卡片视图"</string>
<string name="cant_mark_favortie">"不能将文章标记为收藏"</string>
<string name="cant_unmark_favortie">"无法从收藏中删除项目"</string>
<string name="share">"共享"</string>
<string name="rating_prompt_title">"喜欢这个应用吗?"</string>
<string name="rating_prompt_yes">"是的!"</string>
<string name="rating_prompt_no">"不大喜欢…"</string>
<string name="rating_prompt_feedback_title">"能告诉我们为什么吗?"</string>
<string name="rating_prompt_feedback_yes">"好的!"</string>
<string name="rating_prompt_feedback_no">"以后再说。"</string>
<string name="rating_prompt_rating_title">"太好了!你能在应用商店给我们打分吗?"</string>
<string name="rating_prompt_rating_yes">"当然!"</string>
<string name="rating_prompt_rating_no">"现在不行。"</string>
<string name="rating_prompt_thanks">"谢谢,您的反馈有助于改进应用程序!"</string>
<string name="switch_unread_count">"将未读数在底部显示为一个徽标。"</string>
<string name="switch_unread_count_title">"显示未读数"</string>
<string name="display_all_counts_title">"显示收藏和已读的计数"</string>
@ -83,17 +65,12 @@
<string name="card_height_on">卡片高度将根据内容调整</string>
<string name="card_height_off">卡片高度将被固定</string>
<string name="source_code">源代码</string>
<string name="cant_mark_read">无法将文章标记为已读</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">加载标记时出错..。</string>
<string name="drawer_error_loading_sources">加载源时出错..。</string>
<string name="drawer_item_filters">搜索条件</string>
<string name="drawer_action_clear">清空</string>
<string name="drawer_item_tags">标签</string>
<string name="drawer_item_sources">来源</string>
<string name="drawer_action_edit">编辑</string>
<string name="no_tags_loaded">未加载标签</string>
<string name="no_sources_loaded">未加载数据源</string>
<string name="drawer_loading">正在载入…</string>
<string name="menu_home_search">搜索</string>
<string name="can_delete_source">无法删除数据源…</string>
@ -101,16 +78,9 @@
<string name="pref_header_theme">主题</string>
<string name="default_theme">默认​​​​​</string>
<string name="default_dark_theme">默认值/暗</string>
<string name="pref_header_debug">调试</string>
<string name="self_hosted_cert_switch">使用自托管证书?</string>
<string name="self_signed_cert_warning">出于安全考虑, 默认情况下不支持自签名证书。如果激活此项, 您遇到的任何安全问题我将概不负责。</string>
<string name="pref_selfoss_category">塞尔福斯 Api</string>
<string name="pref_api_items_number_title">已加载项目编号</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">除错标识符</string>
<string name="unique_id_to_clipboard">复制到你的剪贴板的标识符</string>
<string name="display_header_drawer_summary">在侧边栏中显示带有 Selfoss 链接地址的页眉。</string>
<string name="display_header_drawer_title">帐户页眉</string>
<string name="pref_general_infinite_loading_title">翻页时载入更多文章</string>
<string name="translation">翻译</string>
<string name="cant_open_invalid_url">项目链接地址无效。我正在设法解决这个问题,以避免应用程序崩溃。</string>
@ -121,19 +91,12 @@
<string name="reader_action_share">分享</string>
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="add_to_favs_reader">Add to favorites</string>
<string name="remove_to_favs_reader">Remove from favorites</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Enable logging</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Mark item as unread</string>
<string name="pref_header_offline">Offline and cache</string>
@ -142,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -11,14 +11,6 @@
<color name="refresh_progress_1">@color/colorAccentDark</color>
<color name="refresh_progress_2">@color/colorAccent</color>
<color name="refresh_progress_3">@color/pink</color>
<color name="background_grey">#FFe4e4e4</color>
<color name="dark_webview">#FF303030</color>
<color name="dark_webview_text">#FFFFFF</color>
<color name="light_webview">#FFFFFF</color>
<color name="light_webview_text">#212121</color>
<color name="cardBackgroundColor">#FFFFFFFF</color>
<color name="materialDrawerHeaderSelectionText">#212121</color>
<color name="darkBackground">#303030</color>
</resources>

View File

@ -2,16 +2,13 @@
<string name="app_name">"Reader for Selfoss"</string>
<string name="title_activity_login">"Log in"</string>
<string name="prompt_password">"Password"</string>
<string name="prompt_http_password">"HTTP Password"</string>
<string name="action_sign_in">"Go"</string>
<string name="error_invalid_password">"Password not long enough"</string>
<string name="error_field_required">"Field required"</string>
<string name="prompt_url">"Url"</string>
<string name="withLoginSwitch">"Login required ?"</string>
<string name="withHttpLoginSwitch">"HTTP Login required ?"</string>
<string name="login_url_problem">"Oops. You may need to add a \"/\" at the end of the url."</string>
<string name="prompt_login">"Username"</string>
<string name="prompt_http_login">"HTTP Username"</string>
<string name="label_share">"Share"</string>
<string name="readAll">"Read all"</string>
<string name="action_disconnect">"Disconnect"</string>
@ -25,9 +22,6 @@
<string name="wrong_infos">"Check your details again."</string>
<string name="all_posts_not_read">"All posts weren't read"</string>
<string name="all_posts_read">"All posts were read"</string>
<string name="cant_get_favs">"Can't get favorites"</string>
<string name="cant_get_new_elements">"Can't get new articles"</string>
<string name="cant_get_read">"Can't get read articles"</string>
<string name="nothing_here">"Nothing here"</string>
<string name="tab_new">"New"</string>
<string name="tab_read">"All"</string>
@ -47,19 +41,7 @@
<string name="issue_tracker_summary">"Report a bug or ask for a new feature"</string>
<string name="warning_wrong_url">"WARNING"</string>
<string name="pref_switch_card_view_title">"Card View"</string>
<string name="cant_mark_favortie">"Can't mark article as favorite"</string>
<string name="cant_unmark_favortie">"Can't remove item from favorite"</string>
<string name="share">"Share"</string>
<string name="rating_prompt_title">"Enjoying the app ?"</string>
<string name="rating_prompt_yes">"Yes !"</string>
<string name="rating_prompt_no">"Not really …"</string>
<string name="rating_prompt_feedback_title">"Can you tell us why ?"</string>
<string name="rating_prompt_feedback_yes">"OK !"</string>
<string name="rating_prompt_feedback_no">"Not now."</string>
<string name="rating_prompt_rating_title">"Great ! Can you rate us on the Store ?"</string>
<string name="rating_prompt_rating_yes">"Sure !"</string>
<string name="rating_prompt_rating_no">"Not right now."</string>
<string name="rating_prompt_thanks">"Thanks, your feedback help enhance the app !"</string>
<string name="switch_unread_count">"Display the unread count as a badge for the bottom bar."</string>
<string name="switch_unread_count_title">"Display unread count"</string>
<string name="display_all_counts_title">"Display count for favorite and read"</string>
@ -83,17 +65,12 @@
<string name="card_height_on">Cards height will adjust to its content</string>
<string name="card_height_off">Card height will be fixed</string>
<string name="source_code">Source code</string>
<string name="cant_mark_read">Can\'t mark article as read</string>
<string name="cant_mark_unread">Can\'t mark article as unread</string>
<string name="drawer_error_loading_tags">Error loading tags…</string>
<string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="drawer_item_filters">Filters</string>
<string name="drawer_action_clear">clear</string>
<string name="drawer_item_tags">Tags</string>
<string name="drawer_item_sources">Sources</string>
<string name="drawer_action_edit">edit</string>
<string name="no_tags_loaded">No tags loaded</string>
<string name="no_sources_loaded">No sources loaded</string>
<string name="drawer_loading">Loading …</string>
<string name="menu_home_search">Search</string>
<string name="can_delete_source">Can\'t delete the source…</string>
@ -101,17 +78,9 @@
<string name="pref_header_theme">Themes</string>
<string name="default_theme">Default</string>
<string name="default_dark_theme">Default/Dark</string>
<string name="pref_header_debug">Debug</string>
<string name="self_hosted_cert_switch">Using a self hosted certificate ?</string>
<string name="self_signed_cert_warning">Due to security reasons, self signed certificates are not supported by default. By activating this, I\'ll not be responsible of any security problem you encounter.</string>
<string name="pref_selfoss_category">Selfoss Api</string>
<string name="pref_api_items_number_title">Loaded items number</string>
<string name="pref_hidden_tags">Hidden Tags</string>
<string name="summary_debug_identifier">Debug identifier</string>
<string name="unique_id_to_clipboard">Identifier copied to your clipboard</string>
<string
name="display_header_drawer_summary">Display a header with the selfoss instance url on the lateral drawer.</string>
<string name="display_header_drawer_title">Account header</string>
<string name="pref_general_infinite_loading_title">Load more articles on scroll</string>
<string name="translation">Translation</string>
<string name="cant_open_invalid_url">The item url is invalid. I\'m looking into solving this issue so the app won\'t crash.</string>
@ -122,19 +91,12 @@
<string name="reader_action_share">Share</string>
<string name="pref_switch_actions_pager_scroll_on">Mark articles as read when swiping between articles.</string>
<string name="add_to_favs_reader">Add to favorites</string>
<string name="remove_to_favs_reader">Remove from favorites</string>
<string name="pref_content_reader_font_size">Article reader content font size</string>
<string name="pref_header_viewer">Article viewer</string>
<string name="refresh_dialog_message">This will refresh your Selfoss instance.</string>
<string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
<string name="acra_login">Enable logging</string>
<string name="drawer_item_hidden_tags">Hidden Tags</string>
<string name="unmark">Mark item as unread</string>
<string name="pref_header_offline">Offline and cache</string>
@ -143,7 +105,6 @@
<string name="pref_switch_items_caching">Save items for offline use</string>
<string name="pref_switch_update_sources">Check for new sources and tags</string>
<string name="pref_switch_update_sources_summary">Disable this if your server is receiving excessive amounts of database queries.</string>
<string name="no_network_connectivity">Not connected !</string>
<string name="network_connectivity_lost">"Network connection lost"</string>
<string name="network_connectivity_retrieved">"Network connection is now available"</string>
<string name="pref_switch_periodic_refresh">Sync articles</string>

View File

@ -60,12 +60,6 @@
android:title="@string/pref_general_category_displaying">
</PreferenceCategory>
<SwitchPreference
android:defaultValue="false"
android:key="account_header_displaying"
android:summary="@string/display_header_drawer_summary"
android:title="@string/display_header_drawer_title"
app:iconSpaceReserved="false"/>
<SwitchPreference
android:defaultValue="false"
android:key="card_view_active"

View File

@ -1,18 +1,20 @@
package bou.amine.apps.readerforselfossv2.utils
import android.text.format.DateUtils
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import java.time.Instant
import java.time.LocalDateTime
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
actual class DateUtils actual constructor(private val apiMajorVersion: Int) {
actual class DateUtils actual constructor(actual val appSettingsService: AppSettingsService) {
actual fun parseDate(dateString: String): Long {
val FORMATTERV1 = "yyyy-MM-dd HH:mm:ss"
return if (apiMajorVersion >= 4) {
return if (appSettingsService.getApiVersion() >= 4) {
OffsetDateTime.parse(dateString).toInstant().toEpochMilli()
} else {
LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(FORMATTERV1)).toInstant(

View File

@ -5,7 +5,6 @@ import android.text.Html
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import org.jsoup.Jsoup
import java.util.*
import kotlin.collections.ArrayList
actual fun String.getHtmlDecoded(): String {
return Html.fromHtml(this).toString()

View File

@ -1,14 +1,13 @@
package bou.amine.apps.readerforselfossv2.DI
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
import bou.amine.apps.readerforselfossv2.service.ApiDetailsServiceImpl
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import org.kodein.di.DI
import org.kodein.di.bind
import org.kodein.di.instance
import org.kodein.di.singleton
val networkModule by DI.Module {
bind<ApiDetailsService>() with singleton { ApiDetailsServiceImpl() }
bind<AppSettingsService>() with singleton { AppSettingsService() }
bind<SelfossApi>() with singleton { SelfossApi(instance()) }
}

View File

@ -2,25 +2,23 @@ package bou.amine.apps.readerforselfossv2.repository
import bou.amine.apps.readerforselfossv2.dao.*
import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import bou.amine.apps.readerforselfossv2.utils.*
import com.github.ln_12.library.ConnectivityStatus
import com.russhwolf.settings.Settings
import io.github.aakira.napier.Napier
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class Repository(private val api: SelfossApi, private val apiDetails: ApiDetailsService, private val connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) {
val settings = Settings()
class Repository(private val api: SelfossApi, private val appSettingsService: AppSettingsService, connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) {
var items = ArrayList<SelfossModel.Item>()
val isConnectionAvailable = connectivityStatus.isNetworkConnected
var connectionMonitored = false
var baseUrl = apiDetails.getBaseUrl()
var baseUrl = appSettingsService.getBaseUrl()
lateinit var dateUtils: DateUtils
var displayedItems = ItemType.UNREAD
@ -29,10 +27,8 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
var sourceFilter: SelfossModel.Source? = null
var searchFilter: String? = null
var itemsCaching = settings.getBoolean("items_caching", false)
var offlineOverride = false
var apiMajorVersion = 0
var badgeUnread = 0
set(value) {field = if (value < 0) { 0 } else { value } }
var badgeAll = 0
@ -44,6 +40,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
// TODO: Dispatchers.IO not available in KMM, an alternative solution should be found
CoroutineScope(Dispatchers.Main).launch {
updateApiVersion()
dateUtils = DateUtils(appSettingsService)
reloadBadges()
}
}
@ -54,7 +51,6 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
if (isNetworkAvailable()) {
fetchedItems = api.getItems(
displayedItems.type,
settings.getString("prefer_api_items_number", "200").toInt(),
offset = 0,
tagFilter?.tag,
sourceFilter?.id?.toLong(),
@ -62,7 +58,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
null
)
} else {
if (itemsCaching) {
if (appSettingsService.isItemCachingEnabled()) {
fetchedItems = getDBItems().filter {
displayedItems == ItemType.ALL ||
(it.unread && displayedItems == ItemType.UNREAD) ||
@ -84,7 +80,6 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
val offset = items.size
fetchedItems = api.getItems(
displayedItems.type,
settings.getString("prefer_api_items_number", "200").toInt(),
offset,
tagFilter?.tag,
sourceFilter?.id?.toLong(),
@ -100,16 +95,16 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
return items
}
suspend fun getMaxItemsForBackground(itemType: ItemType): List<SelfossModel.Item>? {
private suspend fun getMaxItemsForBackground(itemType: ItemType): List<SelfossModel.Item>? {
return if (isNetworkAvailable()) {
api.getItems(
itemType.type,
200,
0,
tagFilter?.tag,
sourceFilter?.id?.toLong(),
searchFilter,
null
null,
200
)
} else {
emptyList()
@ -142,7 +137,11 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
suspend fun getTags(): List<SelfossModel.Tag>? {
return if (isNetworkAvailable()) {
api.tags()
val apiTags = api.tags()
if (apiTags != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
resetDBTagsWithData(apiTags)
}
apiTags
} else {
getDBTags().map { it.toView() }
}
@ -157,9 +156,12 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
}
suspend fun getSources(): ArrayList<SelfossModel.Source>? {
return if (isNetworkAvailable()) {
api.sources()
val apiSources = api.sources()
if (apiSources != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
resetDBSourcesWithData(apiSources)
}
apiSources
} else {
ArrayList(getDBSources().map { it.toView() })
}
@ -174,7 +176,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
return success
}
suspend fun markAsReadById(id: Int): Boolean {
private suspend fun markAsReadById(id: Int): Boolean {
return if (isNetworkAvailable()) {
api.markAsRead(id.toString())?.isSuccess == true
} else {
@ -193,7 +195,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
return success
}
suspend fun unmarkAsReadById(id: Int): Boolean {
private suspend fun unmarkAsReadById(id: Int): Boolean {
return if (isNetworkAvailable()) {
api.unmarkAsRead(id.toString())?.isSuccess == true
} else {
@ -211,7 +213,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
return success
}
suspend fun starrById(id: Int): Boolean {
private suspend fun starrById(id: Int): Boolean {
return if (isNetworkAvailable()) {
api.starr(id.toString())?.isSuccess == true
} else {
@ -229,7 +231,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
return success
}
suspend fun unstarrById(id: Int): Boolean {
private suspend fun unstarrById(id: Int): Boolean {
return if (isNetworkAvailable()) {
api.unstarr(id.toString())?.isSuccess == true
} else {
@ -309,7 +311,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
spout,
tags,
filter,
apiMajorVersion
appSettingsService.getApiVersion()
)?.isSuccess == true
}
@ -352,38 +354,29 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
return result
}
fun refreshLoginInformation(url: String, login: String, password: String,
httpLogin: String, httpPassword: String,
isSelfSignedCert: Boolean) {
settings.putString("url", url)
settings.putString("login", login)
settings.putString("httpUserName", httpLogin)
settings.putString("password", password)
settings.putString("httpPassword", httpPassword)
settings.putBoolean("isSelfSignedCert", isSelfSignedCert)
fun refreshLoginInformation(url: String, login: String, password: String) {
appSettingsService.refreshLoginInformation(url, login, password)
baseUrl = url
api.refreshLoginInformation()
}
private suspend fun updateApiVersion() {
apiMajorVersion = settings.getInt("apiVersionMajor", 0)
suspend fun updateApiVersion() {
val apiMajorVersion = appSettingsService.getApiVersion()
if (isNetworkAvailable()) {
val fetchedVersion = api.version()
if (fetchedVersion != null) {
apiMajorVersion = fetchedVersion.getApiMajorVersion()
settings.putInt("apiVersionMajor", apiMajorVersion)
if (fetchedVersion != null && fetchedVersion.getApiMajorVersion() != apiMajorVersion) {
appSettingsService.updateApiVersion(fetchedVersion.getApiMajorVersion())
}
}
dateUtils = DateUtils(apiMajorVersion)
}
fun isNetworkAvailable() = isConnectionAvailable.value && !offlineOverride
fun getDBActions(): List<ACTION> =
private fun getDBActions(): List<ACTION> =
db.actionsQueries.actions().executeAsList()
fun deleteDBAction(action: ACTION) =
private fun deleteDBAction(action: ACTION) =
db.actionsQueries.deleteAction(action.id)
fun getDBTags(): List<TAG> = db.tagsQueries.tags().executeAsList()
@ -434,7 +427,9 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
val starredItems = getMaxItemsForBackground(ItemType.STARRED)
insertDBItems(newItems.orEmpty() + allItems.orEmpty() + starredItems.orEmpty())
return newItems
} catch (e: Throwable) {}
} catch (e: Throwable) {
// We do nothing
}
return emptyList()
}

View File

@ -1,19 +1,20 @@
package bou.amine.apps.readerforselfossv2.rest
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.cache.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.client.request.*
import io.ktor.client.request.forms.*
import io.ktor.http.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json
class SelfossApi(private val apiDetailsService: ApiDetailsService) {
class SelfossApi(private val appSettingsService: AppSettingsService) {
var client = createHttpClient()
@ -30,11 +31,14 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
install(Logging) {
logger = object : Logger {
override fun log(message: String) {
apiDetailsService.logApiCalls(message)
appSettingsService.logApiCalls(message)
}
}
level = LogLevel.ALL
}
install(HttpTimeout) {
requestTimeoutMillis = appSettingsService.getApiTimeout()
}
/* TODO: Auth as basic
if (apiDetailsService.getUserName().isNotEmpty() && apiDetailsService.getPassword().isNotEmpty()) {
@ -54,68 +58,68 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
}
fun url(path: String) =
"${apiDetailsService.getBaseUrl()}$path"
"${appSettingsService.getBaseUrl()}$path"
fun refreshLoginInformation() {
apiDetailsService.refresh()
appSettingsService.refreshApiSettings()
client = createHttpClient()
}
suspend fun login(): SelfossModel.SuccessResponse? =
client.get(url("/login")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
suspend fun getItems(
type: String,
items: Int,
offset: Int,
tag: String?,
source: Long?,
search: String?,
updatedSince: String?
updatedSince: String?,
items: Int? = null
): List<SelfossModel.Item>? =
client.get(url("/items")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
parameter("type", type)
parameter("tag", tag)
parameter("source", source)
parameter("search", search)
parameter("updatedsince", updatedSince)
parameter("items", items)
parameter("items", items ?: appSettingsService.getItemsNumber())
parameter("offset", offset)
}.body()
suspend fun stats(): SelfossModel.Stats? =
client.get(url("/stats")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
suspend fun tags(): List<SelfossModel.Tag>? =
client.get(url("/tags")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
suspend fun update(): String? =
client.get(url("/update")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
suspend fun spouts(): Map<String, SelfossModel.Spout>? =
client.get(url("/sources/spouts")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
suspend fun sources(): ArrayList<SelfossModel.Source>? =
client.get(url("/sources/list")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
suspend fun version(): SelfossModel.ApiVersion? =
@ -123,34 +127,34 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? =
client.post(url("/mark/$id")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? =
client.post(url("/unmark/$id")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
suspend fun starr(id: String): SelfossModel.SuccessResponse? =
client.post(url("/starr/$id")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
suspend fun unstarr(id: String): SelfossModel.SuccessResponse? =
client.post(url("/unstarr/$id")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
suspend fun markAllAsRead(ids: List<String>): SelfossModel.SuccessResponse? =
client.submitForm(
url = url("/mark"),
formParameters = Parameters.build {
append("username", apiDetailsService.getUserName())
append("password", apiDetailsService.getPassword())
append("username", appSettingsService.getUserName())
append("password", appSettingsService.getPassword())
ids.map { append("ids[]", it) }
}
).body()
@ -177,7 +181,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
filter: String
): SelfossModel.SuccessResponse? =
client.submitForm(
url = url("/source?username=${apiDetailsService.getUserName()}&password=${apiDetailsService.getPassword()}"),
url = url("/source?username=${appSettingsService.getUserName()}&password=${appSettingsService.getPassword()}"),
formParameters = Parameters.build {
append("title", title)
append("url", url)
@ -195,7 +199,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
filter: String
): SelfossModel.SuccessResponse? =
client.submitForm(
url = url("/source?username=${apiDetailsService.getUserName()}&password=${apiDetailsService.getPassword()}"),
url = url("/source?username=${appSettingsService.getUserName()}&password=${appSettingsService.getPassword()}"),
formParameters = Parameters.build {
append("title", title)
append("url", url)
@ -207,7 +211,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? =
client.delete(url("/source/$id")) {
parameter("username", apiDetailsService.getUserName())
parameter("password", apiDetailsService.getPassword())
parameter("username", appSettingsService.getUserName())
parameter("password", appSettingsService.getPassword())
}.body()
}

View File

@ -1,10 +0,0 @@
package bou.amine.apps.readerforselfossv2.service
interface ApiDetailsService {
fun logApiCalls(message: String)
fun getApiVersion(): Int
fun getBaseUrl(): String
fun getUserName(): String
fun getPassword(): String
fun refresh()
}

View File

@ -1,52 +0,0 @@
package bou.amine.apps.readerforselfossv2.service
import com.russhwolf.settings.Settings
import io.github.aakira.napier.Napier
class ApiDetailsServiceImpl : ApiDetailsService {
val settings: Settings = Settings()
private var _apiVersion: Int = -1
private var _baseUrl: String = ""
private var _userName: String = ""
private var _password: String = ""
override fun logApiCalls(message: String) {
Napier.d(message, tag = "LogApiCalls")
}
override fun getApiVersion(): Int {
if (_apiVersion == -1) {
_apiVersion = settings.getInt("apiVersionMajor", -1)
return _apiVersion
}
return _apiVersion
}
override fun getBaseUrl(): String {
if (_baseUrl.isEmpty()) {
_baseUrl = settings.getString("url", "")
}
return _baseUrl
}
override fun getUserName(): String {
if (_userName.isEmpty()) {
_userName = settings.getString("login", "")
}
return _userName
}
override fun getPassword(): String {
if (_password.isEmpty()) {
_password = settings.getString("password", "")
}
return _password
}
override fun refresh() {
_password = settings.getString("password", "")
_userName = settings.getString("login", "")
_baseUrl = settings.getString("url", "")
_apiVersion = settings.getInt("apiVersionMajor", -1)
}
}

View File

@ -0,0 +1,413 @@
package bou.amine.apps.readerforselfossv2.service
import com.russhwolf.settings.Settings
import io.github.aakira.napier.Napier
import io.ktor.client.plugins.*
class AppSettingsService {
val settings: Settings = Settings()
// Api related
private var _apiVersion: Int = -1
private var _baseUrl: String = ""
private var _userName: String = ""
private var _password: String = ""
// User settings related
private var _itemsCaching: Boolean? = null
private var _internalBrowser: Boolean? = null
private var _articleViewer: Boolean? = null
private var _shouldBeCardView: Boolean? = null
private var _displayUnreadCount: Boolean? = null
private var _displayAllCount: Boolean? = null
private var _fullHeightCards: Boolean? = null
private var _updateSources: Boolean? = null
private var _periodicRefresh: Boolean? = null
private var _refreshWhenChargingOnly: Boolean? = null
private var _infiniteLoading: Boolean? = null
private var _notifyNewItems: Boolean? = null
private var _itemsNumber: Int? = null
private var _apiTimeout: Long? = null
private var _hiddenTags: List<String>? = null
private var _refreshMinutes: Long = 360
private var _markOnScroll: Boolean? = null
private var _activeAlignment: Int? = null
private var _fontSize: Int? = null
private var _staticBar: Boolean? = null
private var _font: String = ""
init {
refreshApiSettings()
refreshUserSettings()
}
fun logApiCalls(message: String) {
Napier.d(message, tag = "LogApiCalls")
}
fun getApiVersion(): Int {
if (_apiVersion == -1) {
refreshApiVersion()
return _apiVersion
}
return _apiVersion
}
fun refreshApiVersion() {
_apiVersion = settings.getInt("apiVersionMajor", -1)
}
fun getBaseUrl(): String {
if (_baseUrl.isEmpty()) {
refreshBaseUrl()
}
return _baseUrl
}
fun getUserName(): String {
if (_userName.isEmpty()) {
refreshUsername()
}
return _userName
}
fun getPassword(): String {
if (_password.isEmpty()) {
refreshPassword()
}
return _password
}
fun getItemsNumber(): Int {
if (_itemsNumber == null) {
refreshItemsNumber()
}
return _itemsNumber!!
}
fun refreshItemsNumber() {
_itemsNumber = settings.getString("prefer_api_items_number", "200").toInt()
}
fun getApiTimeout(): Long {
if (_apiTimeout == null) {
refreshApiTimeout()
}
return _apiTimeout!!
}
private fun refreshApiTimeout() {
val settingsTimeout = settings.getLong("api_timeout", HttpTimeout.INFINITE_TIMEOUT_MS)
_apiTimeout = if (settingsTimeout > 0) settingsTimeout else HttpTimeout.INFINITE_TIMEOUT_MS
}
private fun refreshBaseUrl() {
_baseUrl = settings.getString("url", "")
}
private fun refreshUsername() {
_userName = settings.getString("login", "")
}
private fun refreshPassword() {
_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() {
_articleViewer = settings.getBoolean("prefer_article_viewer", true)
}
fun isArticleViewerEnabled(): Boolean {
if (_articleViewer != null) {
refreshArticleViewerEnabled()
}
return _articleViewer == true
}
private fun refreshShouldBeCardViewEnabled() {
_shouldBeCardView = settings.getBoolean("card_view_active", false)
}
fun isCardViewEnabled(): Boolean {
if (_shouldBeCardView != null) {
refreshShouldBeCardViewEnabled()
}
return _shouldBeCardView == true
}
private fun refreshDisplayUnreadCountEnabled() {
_displayUnreadCount = settings.getBoolean("display_unread_count", true)
}
fun isDisplayUnreadCountEnabled(): Boolean {
if (_displayUnreadCount != null) {
refreshDisplayUnreadCountEnabled()
}
return _displayUnreadCount == true
}
private fun refreshDisplayAllCountEnabled() {
_displayAllCount = settings.getBoolean("display_other_count", false)
}
fun isDisplayAllCountEnabled(): Boolean {
if (_displayAllCount != null) {
refreshDisplayAllCountEnabled()
}
return _displayAllCount == true
}
private fun refreshFullHeightCardsEnabled() {
_fullHeightCards = settings.getBoolean("full_height_cards", false)
}
fun isFullHeightCardsEnabled(): Boolean {
if (_fullHeightCards != null) {
refreshFullHeightCardsEnabled()
}
return _fullHeightCards == true
}
private fun refreshUpdateSourcesEnabled() {
_updateSources = settings.getBoolean("update_sources", true)
}
fun isUpdateSourcesEnabled(): Boolean {
if (_updateSources != null) {
refreshUpdateSourcesEnabled()
}
return _updateSources == true
}
private fun refreshPeriodicRefreshEnabled() {
_periodicRefresh = settings.getBoolean("periodic_refresh", false)
}
fun isPeriodicRefreshEnabled(): Boolean {
if (_periodicRefresh != null) {
refreshPeriodicRefreshEnabled()
}
return _periodicRefresh == true
}
private fun refreshRefreshWhenChargingOnlyEnabled() {
_refreshWhenChargingOnly = settings.getBoolean("refresh_when_charging", false)
}
fun isRefreshWhenChargingOnlyEnabled(): Boolean {
if (_refreshWhenChargingOnly != null) {
refreshRefreshWhenChargingOnlyEnabled()
}
return _refreshWhenChargingOnly == true
}
private fun refreshRefreshMinutes() {
_refreshMinutes = settings.getString("periodic_refresh_minutes", "360").toLong()
if (_refreshMinutes <= 15) {
_refreshMinutes = 15
}
}
fun getRefreshMinutes(): Long {
if (_refreshMinutes != null) {
refreshRefreshMinutes()
}
return _refreshMinutes
}
private fun refreshHiddenTags() {
if (settings.getString("hidden_tags", "").isNotEmpty()) {
_hiddenTags = settings.getString("hidden_tags", "").replace("\\s".toRegex(), "").split(",")
}
}
fun getHiddenTags(): List<String> {
if (_hiddenTags != null) {
refreshHiddenTags()
}
return _hiddenTags.orEmpty()
}
private fun refreshInfiniteLoadingEnabled() {
_infiniteLoading = settings.getBoolean("infinite_loading", false)
}
fun isInfiniteLoadingEnabled(): Boolean {
if (_infiniteLoading != null) {
refreshInfiniteLoadingEnabled()
}
return _infiniteLoading == true
}
private fun refreshItemCachingEnabled() {
_itemsCaching = settings.getBoolean("items_caching", false)
}
fun isItemCachingEnabled(): Boolean {
if (_itemsCaching != null) {
refreshItemCachingEnabled()
}
return _itemsCaching == true
}
private fun refreshNotifyNewItemsEnabled() {
_notifyNewItems = settings.getBoolean("notify_new_items", false)
}
fun isNotifyNewItemsEnabled(): Boolean {
if (_notifyNewItems != null) {
refreshNotifyNewItemsEnabled()
}
return _notifyNewItems == true
}
private fun refreshMarkOnScrollEnabled() {
_markOnScroll = settings.getBoolean("mark_on_scroll", false)
}
fun isMarkOnScrollEnabled(): Boolean {
if (_markOnScroll != null) {
refreshMarkOnScrollEnabled()
}
return _markOnScroll == true
}
private fun refreshActiveAllignment() {
_activeAlignment = settings.getInt("text_align", JUSTIFY)
}
fun getActiveAllignment(): Int {
if (_activeAlignment != null) {
refreshActiveAllignment()
}
return _activeAlignment ?: JUSTIFY
}
fun changeAllignment(allignment: Int) {
settings.putInt("text_align", allignment)
_activeAlignment = allignment
}
private fun refreshFontSize() {
_fontSize = settings.getString("reader_font_size", "16").toInt()
}
fun getFontSize(): Int {
if (_fontSize != null) {
refreshFontSize()
}
return _fontSize ?: 16
}
private fun refreshStaticBarEnabled() {
_staticBar = settings.getBoolean("reader_static_bar", false)
}
fun isStaticBarEnabled(): Boolean {
if (_staticBar != null) {
refreshStaticBarEnabled()
}
return _staticBar == true
}
private fun refreshFont() {
_font = settings.getString("reader_font", "")
}
fun getFont(): String {
if (_font != null) {
refreshFont()
}
return _font
}
fun refreshApiSettings() {
refreshPassword()
refreshUsername()
refreshBaseUrl()
refreshApiVersion()
}
fun refreshUserSettings() {
refreshItemsNumber()
refreshApiTimeout()
refreshInternalBrowserEnabled()
refreshArticleViewerEnabled()
refreshShouldBeCardViewEnabled()
refreshDisplayUnreadCountEnabled()
refreshDisplayAllCountEnabled()
refreshFullHeightCardsEnabled()
refreshUpdateSourcesEnabled()
refreshPeriodicRefreshEnabled()
refreshRefreshWhenChargingOnlyEnabled()
refreshRefreshMinutes()
refreshHiddenTags()
refreshInfiniteLoadingEnabled()
refreshItemCachingEnabled()
refreshNotifyNewItemsEnabled()
refreshMarkOnScrollEnabled()
refreshActiveAllignment()
refreshFontSize()
refreshFont()
refreshStaticBarEnabled()
}
fun refreshLoginInformation(
url: String,
login: String,
password: String
) {
settings.putString("url", url)
settings.putString("login", login)
settings.putString("password", password)
refreshApiSettings()
}
fun resetLoginInformation() {
settings.remove("url")
settings.remove("login")
settings.remove("password")
refreshApiSettings()
}
fun updateApiVersion(apiMajorVersion: Int) {
settings.putInt("apiVersionMajor", apiMajorVersion)
refreshApiVersion()
}
fun clearAll() {
settings.clear()
refreshApiSettings()
refreshUserSettings()
}
fun disableArticleViewer() {
settings.putBoolean("prefer_article_viewer", false)
refreshArticleViewerEnabled()
}
companion object {
const val translationUrl = "https://crwd.in/readerforselfoss"
const val sourceUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform"
const val trackerUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/issues"
const val syncChannelId = "sync-channel-id"
const val newItemsChannelId = "new-items-channel-id"
const val JUSTIFY = 1
const val ALIGN_LEFT = 2
}
}

View File

@ -1,12 +1,15 @@
package bou.amine.apps.readerforselfossv2.utils
import bou.amine.apps.readerforselfossv2.model.SelfossModel
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
fun SelfossModel.Item.parseDate(dateUtils: DateUtils): Long =
dateUtils.parseDate(this.datetime)
expect class DateUtils(apiMajorVersion: Int) {
expect class DateUtils constructor(appSettingsService: AppSettingsService) {
val appSettingsService: AppSettingsService // This is needed because of https://stackoverflow.com/a/65249085
fun parseDate(dateString: String): Long
fun parseRelativeDate(dateString: String): String

View File

@ -1,6 +1,8 @@
package bou.amine.apps.readerforselfossv2.utils
actual class DateUtils actual constructor(apiMajorVersion: Int) {
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
actual class DateUtils actual constructor(actual val appSettingsService: AppSettingsService) {
actual fun parseDate(dateString: String): Long {
TODO("Not yet implemented")
}

View File

@ -1,6 +1,8 @@
package bou.amine.apps.readerforselfossv2.utils
actual class DateUtils actual constructor(apiMajorVersion: Int) {
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
actual class DateUtils actual constructor(actual val appSettingsService: AppSettingsService) {
actual fun parseDate(dateString: String): Long {
TODO("Not yet implemented")
}