Compare commits
22 Commits
v172002032
...
v172101010
Author | SHA1 | Date | |
---|---|---|---|
193f538d29 | |||
7f45db0473 | |||
d89423b9ac | |||
25fd869c01 | |||
d1d956b77a | |||
41c14362a8 | |||
6fa8c901fc | |||
db124ab9de | |||
953940690d | |||
918661be2d | |||
7b8a5c9a56 | |||
2d5ab7bf0c | |||
9ba281befb | |||
00c8eed034 | |||
a1e4f89cd1 | |||
36a43b3861 | |||
aa6d470f40 | |||
0046a8a477 | |||
43ff9d186a | |||
73dae304be | |||
66103a451b | |||
600c62316d |
18
CHANGELOG.md
18
CHANGELOG.md
@ -26,6 +26,22 @@
|
||||
|
||||
- Closing #38. Only doing api calls on network available.
|
||||
|
||||
- Closing #298 and #287. Issues with Listview rendering
|
||||
|
||||
- Closing #290. Fixing back button issue in Settings
|
||||
|
||||
- Closing #300. Fixing issues when displaying some special characters.
|
||||
|
||||
- Closing #310. Some feeds don't have icons nor thumbnails.
|
||||
|
||||
- Closing #178. Expending images on tap.
|
||||
|
||||
- Closing #323. Old issue with textview not having the right color.
|
||||
|
||||
- Closing #324. Svg images loading crashes the app.
|
||||
|
||||
- Closing #322. App crashed because of svg images.
|
||||
|
||||
**1.6.x**
|
||||
|
||||
- Handling hidden tags.
|
||||
@ -46,6 +62,8 @@
|
||||
|
||||
- Fixes #215, #208.
|
||||
|
||||
- Fixes #328.
|
||||
|
||||
**1.5.7.x**
|
||||
|
||||
- Added confirmation to the mark as read and update menues.
|
||||
|
16
README.md
16
README.md
@ -4,8 +4,24 @@
|
||||
|
||||
It's an RSS Reader for Android, that **only** works with [Selfoss](https://selfoss.aditu.de/)
|
||||
|
||||
**The project is not dead at all.**
|
||||
|
||||
I still want to work on it, but for the last few months, I didn't have that much time to do so.
|
||||
|
||||
If you are a developer, don't hesitate to help with PRs.
|
||||
|
||||
If you are a user, you can still create new issues. I'll fix them when I can.
|
||||
|
||||
<a href="https://f-droid.org/packages/apps.amine.bou.readerforselfoss"><img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="100"></a>
|
||||
|
||||
## Screen captures
|
||||
|
||||
<img src="res//fr-card.png?raw=true" alt="card view" width="400"/> <img src="res//fr-list.png?raw=true" alt="list view" width="400"/>
|
||||
|
||||
## Like my app ?
|
||||
|
||||
<a href="https://www.buymeacoffee.com/aminecmi" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/lato-orange.png" alt="Buy Me A Coffee" style="height: 51px !important;width: 217px !important;" ></a>
|
||||
|
||||
## Want to help ?
|
||||
|
||||
1. **You'll have to have a Selfoss instance running.** You'll find everything you need to install it [here](https://selfoss.aditu.de/).
|
||||
|
@ -24,12 +24,12 @@ def versionNameFromGit() {
|
||||
return gitVersion()
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
@ -37,12 +37,12 @@ android {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion '28.0.3'
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion '30.0.3'
|
||||
defaultConfig {
|
||||
applicationId "apps.amine.bou.readerforselfoss"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
targetSdkVersion 30
|
||||
versionCode versionCodeFromGit()
|
||||
versionName versionNameFromGit()
|
||||
|
||||
@ -85,23 +85,24 @@ android {
|
||||
|
||||
dependencies {
|
||||
// Testing
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-beta01'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0-beta01'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0-alpha02'
|
||||
androidTestImplementation 'androidx.test:runner:1.3.1-alpha02'
|
||||
// Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.2.0-beta01'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0-alpha02'
|
||||
// Espresso-intents for validation and stubbing of Intents
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.2.0-beta01'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0-alpha02'
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
// Android Support
|
||||
implementation "androidx.appcompat:appcompat:$androidx_version"
|
||||
implementation "com.google.android.material:material:1.1.0-alpha06"
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0-alpha05"
|
||||
implementation "androidx.appcompat:appcompat:1.3.0-alpha02"
|
||||
implementation 'com.google.android.material:material:1.3.0-beta01'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.0-beta01'
|
||||
implementation "androidx.legacy:legacy-support-v4:$android_version"
|
||||
implementation "androidx.vectordrawable:vectordrawable:1.1.0-beta01"
|
||||
implementation "androidx.browser:browser:$android_version"
|
||||
implementation 'androidx.vectordrawable:vectordrawable:1.2.0-alpha02'
|
||||
implementation "androidx.browser:browser:1.3.0"
|
||||
implementation "androidx.cardview:cardview:$android_version"
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha5'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.0-alpha2'
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
|
||||
//multidex
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
@ -137,13 +138,16 @@ dependencies {
|
||||
// Pager
|
||||
implementation 'me.relex:circleindicator:2.0.0@aar'
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.1.0-beta01'
|
||||
//PhotoView
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.0.0'
|
||||
|
||||
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
|
||||
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
|
||||
implementation 'androidx.core:core-ktx:1.5.0-alpha05'
|
||||
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata:2.3.0-rc01"
|
||||
implementation "androidx.lifecycle:lifecycle-common-java8:2.3.0-rc01"
|
||||
|
||||
implementation "androidx.room:room-runtime:2.3.0-alpha04"
|
||||
kapt "androidx.room:room-compiler:2.3.0-alpha04"
|
||||
|
||||
implementation "android.arch.work:work-runtime-ktx:$work_version"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,226 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 4,
|
||||
"identityHash": "9cf8b03d32f80dfd58160599a1df197d",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "tags",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tag` TEXT NOT NULL, `color` TEXT NOT NULL, `unread` INTEGER NOT NULL, PRIMARY KEY(`tag`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "tag",
|
||||
"columnName": "tag",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "color",
|
||||
"columnName": "color",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "unread",
|
||||
"columnName": "unread",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"tag"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "sources",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `title` TEXT NOT NULL, `tags` TEXT NOT NULL, `spout` TEXT NOT NULL, `error` TEXT NOT NULL, `icon` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tags",
|
||||
"columnName": "tags",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "spout",
|
||||
"columnName": "spout",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "error",
|
||||
"columnName": "error",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "icon",
|
||||
"columnName": "icon",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "items",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `datetime` TEXT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `unread` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `thumbnail` TEXT, `icon` TEXT, `link` TEXT NOT NULL, `sourcetitle` TEXT NOT NULL, `tags` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "datetime",
|
||||
"columnName": "datetime",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "content",
|
||||
"columnName": "content",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "unread",
|
||||
"columnName": "unread",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "starred",
|
||||
"columnName": "starred",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "thumbnail",
|
||||
"columnName": "thumbnail",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "icon",
|
||||
"columnName": "icon",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "link",
|
||||
"columnName": "link",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "sourcetitle",
|
||||
"columnName": "sourcetitle",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tags",
|
||||
"columnName": "tags",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "actions",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `articleid` TEXT NOT NULL, `read` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `unstarred` INTEGER NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "articleId",
|
||||
"columnName": "articleid",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "read",
|
||||
"columnName": "read",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "unread",
|
||||
"columnName": "unread",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "starred",
|
||||
"columnName": "starred",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "unstarred",
|
||||
"columnName": "unstarred",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"9cf8b03d32f80dfd58160599a1df197d\")"
|
||||
]
|
||||
}
|
||||
}
|
@ -62,6 +62,9 @@
|
||||
<activity
|
||||
android:name=".ReaderActivity">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ImageActivity">
|
||||
</activity>
|
||||
|
||||
<meta-data
|
||||
android:name="apps.amine.bou.readerforselfoss.utils.glide.SelfSignedGlideModule"
|
||||
|
@ -92,7 +92,7 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
this,
|
||||
this@AddSourceActivity,
|
||||
settings.getBoolean("isSelfSignedCert", false),
|
||||
prefs.getString("api_timeout", "-1").toLong()
|
||||
prefs.getString("api_timeout", "-1")!!.toLong()
|
||||
)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
mustLoginToAddSource()
|
||||
|
@ -33,6 +33,7 @@ import apps.amine.bou.readerforselfoss.persistence.database.AppDatabase
|
||||
import apps.amine.bou.readerforselfoss.persistence.entities.ActionEntity
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_1_2
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_2_3
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_3_4
|
||||
import apps.amine.bou.readerforselfoss.settings.SettingsActivity
|
||||
import apps.amine.bou.readerforselfoss.themes.AppColors
|
||||
import apps.amine.bou.readerforselfoss.themes.Toppings
|
||||
@ -164,7 +165,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
|
||||
db = Room.databaseBuilder(
|
||||
applicationContext,
|
||||
AppDatabase::class.java, "selfoss-database"
|
||||
).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).build()
|
||||
).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).addMigrations(MIGRATION_3_4).build()
|
||||
|
||||
|
||||
customTabActivityHelper = CustomTabActivityHelper()
|
||||
@ -176,7 +177,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
|
||||
this,
|
||||
this@HomeActivity,
|
||||
settings.getBoolean("isSelfSignedCert", false),
|
||||
sharedPref.getString("api_timeout", "-1").toLong()
|
||||
sharedPref.getString("api_timeout", "-1")!!.toLong()
|
||||
)
|
||||
items = ArrayList()
|
||||
allItems = ArrayList()
|
||||
@ -388,19 +389,19 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
|
||||
displayUnreadCount = sharedPref.getBoolean("display_unread_count", true)
|
||||
displayAllCount = sharedPref.getBoolean("display_other_count", false)
|
||||
fullHeightCards = sharedPref.getBoolean("full_height_cards", false)
|
||||
itemsNumber = sharedPref.getString("prefer_api_items_number", "200").toInt()
|
||||
userIdentifier = sharedPref.getString("unique_id", "")
|
||||
itemsNumber = sharedPref.getString("prefer_api_items_number", "200")!!.toInt()
|
||||
userIdentifier = sharedPref.getString("unique_id", "")!!
|
||||
displayAccountHeader = sharedPref.getBoolean("account_header_displaying", false)
|
||||
infiniteScroll = sharedPref.getBoolean("infinite_loading", false)
|
||||
itemsCaching = sharedPref.getBoolean("items_caching", false)
|
||||
hiddenTags = if (sharedPref.getString("hidden_tags", "").isNotEmpty()) {
|
||||
sharedPref.getString("hidden_tags", "").replace("\\s".toRegex(), "").split(",")
|
||||
hiddenTags = if (sharedPref.getString("hidden_tags", "")!!.isNotEmpty()) {
|
||||
sharedPref.getString("hidden_tags", "")!!.replace("\\s".toRegex(), "").split(",")
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
periodicRefresh = sharedPref.getBoolean("periodic_refresh", false)
|
||||
refreshWhenChargingOnly = sharedPref.getBoolean("refresh_when_charging", false)
|
||||
refreshMinutes = sharedPref.getString("periodic_refresh_minutes", "360").toLong()
|
||||
refreshMinutes = sharedPref.getString("periodic_refresh_minutes", "360")!!.toLong()
|
||||
|
||||
if (refreshMinutes <= 15) {
|
||||
refreshMinutes = 15
|
||||
@ -449,7 +450,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
|
||||
if (displayAccountHeader) {
|
||||
accountHeader {
|
||||
background = R.drawable.bg
|
||||
profile(settings.getString("url", "")) {
|
||||
profile(settings.getString("url", "")!!) {
|
||||
iconDrawable = resources.getDrawable(R.mipmap.ic_launcher)
|
||||
}
|
||||
selectionListEnabledForSingleProfile = false
|
||||
@ -603,7 +604,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
|
||||
} else {
|
||||
for (tag in maybeSources) {
|
||||
val item = PrimaryDrawerItem()
|
||||
.withName(tag.title)
|
||||
.withName(tag.getTitleDecoded())
|
||||
.withIdentifier(tag.id.toLong())
|
||||
.withOnDrawerItemClickListener { _, _, _ ->
|
||||
allItems = ArrayList()
|
||||
@ -683,13 +684,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
|
||||
.withIconTintingEnabled(true)
|
||||
.withOnDrawerItemClickListener { _, _, _ ->
|
||||
LibsBuilder()
|
||||
.withActivityStyle(
|
||||
if (appColors.isDarkTheme) {
|
||||
Libs.ActivityStyle.DARK
|
||||
} else {
|
||||
Libs.ActivityStyle.LIGHT_DARK_TOOLBAR
|
||||
}
|
||||
)
|
||||
.withAboutIconShown(true)
|
||||
.withAboutVersionShown(true)
|
||||
.start(this@HomeActivity)
|
||||
|
@ -0,0 +1,52 @@
|
||||
package apps.amine.bou.readerforselfoss
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||
import apps.amine.bou.readerforselfoss.fragments.ImageFragment
|
||||
import kotlinx.android.synthetic.main.activity_reader.*
|
||||
|
||||
class ImageActivity : AppCompatActivity() {
|
||||
private lateinit var allImages : ArrayList<String>
|
||||
private var position : Int = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(R.layout.activity_image)
|
||||
|
||||
setSupportActionBar(toolBar)
|
||||
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
allImages = intent.getStringArrayListExtra("allImages") as ArrayList<String>
|
||||
position = intent.getIntExtra("position", 0)
|
||||
|
||||
pager.adapter = ScreenSlidePagerAdapter(supportFragmentManager)
|
||||
pager.currentItem = position
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm, FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
||||
|
||||
override fun getCount(): Int {
|
||||
return allImages.size
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): ImageFragment {
|
||||
return ImageFragment.newInstance(allImages[position])
|
||||
}
|
||||
}
|
||||
}
|
@ -52,11 +52,11 @@ class LoginActivity : AppCompatActivity() {
|
||||
handleBaseUrlFail()
|
||||
|
||||
settings = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||
userIdentifier = settings.getString("unique_id", "")
|
||||
userIdentifier = settings.getString("unique_id", "")!!
|
||||
|
||||
editor = settings.edit()
|
||||
|
||||
if (settings.getString("url", "").isNotEmpty()) {
|
||||
if (settings.getString("url", "")!!.isNotEmpty()) {
|
||||
goToMain()
|
||||
}
|
||||
|
||||
@ -284,7 +284,6 @@ class LoginActivity : AppCompatActivity() {
|
||||
return when (item.itemId) {
|
||||
R.id.about -> {
|
||||
LibsBuilder()
|
||||
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
|
||||
.withAboutIconShown(true)
|
||||
.withAboutVersionShown(true)
|
||||
.start(this)
|
||||
|
@ -26,7 +26,7 @@ class MyApp : MultiDexApplication() {
|
||||
config = Config(baseContext)
|
||||
|
||||
val prefs = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||
if (prefs.getString("unique_id", "").isEmpty()) {
|
||||
if (prefs.getString("unique_id", "")!!.isEmpty()) {
|
||||
val editor = prefs.edit()
|
||||
editor.putString("unique_id", randomUUID().toString())
|
||||
editor.apply()
|
||||
|
@ -25,6 +25,7 @@ import apps.amine.bou.readerforselfoss.persistence.database.AppDatabase
|
||||
import apps.amine.bou.readerforselfoss.persistence.entities.ActionEntity
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_1_2
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_2_3
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_3_4
|
||||
import apps.amine.bou.readerforselfoss.themes.AppColors
|
||||
import apps.amine.bou.readerforselfoss.themes.Toppings
|
||||
import apps.amine.bou.readerforselfoss.transformers.DepthPageTransformer
|
||||
@ -81,7 +82,7 @@ class ReaderActivity : AppCompatActivity() {
|
||||
db = Room.databaseBuilder(
|
||||
applicationContext,
|
||||
AppDatabase::class.java, "selfoss-database"
|
||||
).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).build()
|
||||
).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).addMigrations(MIGRATION_3_4).build()
|
||||
|
||||
val scoop = Scoop.getInstance()
|
||||
scoop.bind(this, Toppings.PRIMARY.value, toolBar)
|
||||
@ -99,7 +100,7 @@ class ReaderActivity : AppCompatActivity() {
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
editor = prefs.edit()
|
||||
|
||||
userIdentifier = prefs.getString("unique_id", "")
|
||||
userIdentifier = prefs.getString("unique_id", "")!!
|
||||
markOnScroll = prefs.getBoolean("mark_on_scroll", false)
|
||||
activeAlignment = prefs.getInt("text_align", JUSTIFY)
|
||||
|
||||
@ -107,7 +108,7 @@ class ReaderActivity : AppCompatActivity() {
|
||||
this,
|
||||
this@ReaderActivity,
|
||||
settings.getBoolean("isSelfSignedCert", false),
|
||||
prefs.getString("api_timeout", "-1").toLong()
|
||||
prefs.getString("api_timeout", "-1")!!.toLong()
|
||||
)
|
||||
|
||||
if (allItems.isEmpty()) {
|
||||
|
@ -64,7 +64,7 @@ class SourcesActivity : AppCompatActivity() {
|
||||
this,
|
||||
this@SourcesActivity,
|
||||
settings.getBoolean("isSelfSignedCert", false),
|
||||
prefs.getString("api_timeout", "-1").toLong()
|
||||
prefs.getString("api_timeout", "-1")!!.toLong()
|
||||
)
|
||||
var items: ArrayList<Source> = ArrayList()
|
||||
|
||||
|
@ -4,12 +4,12 @@ import android.app.Activity
|
||||
import android.content.Context
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.text.Html
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView.ScaleType
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import apps.amine.bou.readerforselfoss.R
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||
@ -35,6 +35,10 @@ import com.bumptech.glide.Glide
|
||||
import com.like.LikeButton
|
||||
import com.like.OnLikeListener
|
||||
import kotlinx.android.synthetic.main.card_item.view.*
|
||||
import kotlinx.android.synthetic.main.card_item.view.itemImage
|
||||
import kotlinx.android.synthetic.main.card_item.view.sourceTitleAndDate
|
||||
import kotlinx.android.synthetic.main.card_item.view.title
|
||||
import kotlinx.android.synthetic.main.list_item.view.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
@ -69,13 +73,22 @@ class ItemCardAdapter(
|
||||
|
||||
|
||||
holder.mView.favButton.isLiked = itm.starred
|
||||
holder.mView.title.text = Html.fromHtml(itm.title)
|
||||
holder.mView.title.text = itm.getTitleDecoded()
|
||||
holder.mView.title.setTextColor(ContextCompat.getColor(
|
||||
c,
|
||||
appColors.textColor
|
||||
))
|
||||
holder.mView.title.setOnTouchListener(LinkOnTouchListener())
|
||||
|
||||
holder.mView.title.setLinkTextColor(appColors.colorAccent)
|
||||
|
||||
holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText()
|
||||
|
||||
holder.mView.sourceTitleAndDate.setTextColor(ContextCompat.getColor(
|
||||
c,
|
||||
appColors.textColor
|
||||
))
|
||||
|
||||
if (!fullHeightCards) {
|
||||
holder.mView.itemImage.maxHeight = imageMaxHeight
|
||||
holder.mView.itemImage.scaleType = ScaleType.CENTER_CROP
|
||||
@ -91,13 +104,13 @@ class ItemCardAdapter(
|
||||
}
|
||||
|
||||
if (itm.getIcon(c).isEmpty()) {
|
||||
val color = generator.getColor(itm.sourcetitle)
|
||||
val color = generator.getColor(itm.getSourceTitle())
|
||||
|
||||
val drawable =
|
||||
TextDrawable
|
||||
.builder()
|
||||
.round()
|
||||
.build(itm.sourcetitle.toTextDrawableString(c), color)
|
||||
.build(itm.getSourceTitle().toTextDrawableString(c), color)
|
||||
holder.mView.sourceImage.setImageDrawable(drawable)
|
||||
} else {
|
||||
c.circularBitmapDrawable(config, itm.getIcon(c), holder.mView.sourceImage)
|
||||
@ -181,7 +194,7 @@ class ItemCardAdapter(
|
||||
|
||||
mView.shareBtn.setOnClickListener {
|
||||
val item = items[adapterPosition]
|
||||
c.shareLink(item.getLinkDecoded(), item.title)
|
||||
c.shareLink(item.getLinkDecoded(), item.getTitleDecoded())
|
||||
}
|
||||
|
||||
mView.browserBtn.setOnClickListener {
|
||||
|
@ -4,7 +4,6 @@ import android.app.Activity
|
||||
import android.content.Context
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.text.Html
|
||||
import android.text.Spannable
|
||||
import android.text.style.ClickableSpan
|
||||
import android.util.TypedValue
|
||||
@ -14,6 +13,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import apps.amine.bou.readerforselfoss.R
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.Item
|
||||
import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
|
||||
@ -71,7 +71,12 @@ class ItemListAdapter(
|
||||
val itm = items[position]
|
||||
|
||||
|
||||
holder.mView.title.text = Html.fromHtml(itm.title)
|
||||
holder.mView.title.text = itm.getTitleDecoded()
|
||||
|
||||
holder.mView.title.setTextColor(ContextCompat.getColor(
|
||||
c,
|
||||
appColors.textColor
|
||||
))
|
||||
|
||||
holder.mView.title.setOnTouchListener(LinkOnTouchListener())
|
||||
|
||||
@ -79,33 +84,21 @@ class ItemListAdapter(
|
||||
|
||||
holder.mView.sourceTitleAndDate.text = itm.sourceAndDateText()
|
||||
|
||||
holder.mView.sourceTitleAndDate.setTextColor(ContextCompat.getColor(
|
||||
c,
|
||||
appColors.textColor
|
||||
))
|
||||
|
||||
if (itm.getThumbnail(c).isEmpty()) {
|
||||
val sizeInInt = 46
|
||||
val sizeInDp = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, sizeInInt.toFloat(), c.resources
|
||||
.displayMetrics
|
||||
).toInt()
|
||||
|
||||
val marginInInt = 16
|
||||
val marginInDp = TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, marginInInt.toFloat(), c.resources
|
||||
.displayMetrics
|
||||
).toInt()
|
||||
|
||||
val params = holder.mView.itemImage.layoutParams as ViewGroup.MarginLayoutParams
|
||||
params.height = sizeInDp
|
||||
params.width = sizeInDp
|
||||
params.setMargins(marginInDp, 0, 0, 0)
|
||||
holder.mView.itemImage.layoutParams = params
|
||||
|
||||
if (itm.getIcon(c).isEmpty()) {
|
||||
val color = generator.getColor(itm.sourcetitle)
|
||||
val color = generator.getColor(itm.getSourceTitle())
|
||||
|
||||
val drawable =
|
||||
TextDrawable
|
||||
.builder()
|
||||
.round()
|
||||
.build(itm.sourcetitle.toTextDrawableString(c), color)
|
||||
.build(itm.getSourceTitle().toTextDrawableString(c), color)
|
||||
|
||||
holder.mView.itemImage.setImageDrawable(drawable)
|
||||
} else {
|
||||
|
@ -46,19 +46,19 @@ class SourcesListAdapter(
|
||||
config = Config(c)
|
||||
|
||||
if (itm.getIcon(c).isEmpty()) {
|
||||
val color = generator.getColor(itm.title)
|
||||
val color = generator.getColor(itm.getTitleDecoded())
|
||||
|
||||
val drawable =
|
||||
TextDrawable
|
||||
.builder()
|
||||
.round()
|
||||
.build(itm.title.toTextDrawableString(c), color)
|
||||
.build(itm.getTitleDecoded().toTextDrawableString(c), color)
|
||||
holder.mView.itemImage.setImageDrawable(drawable)
|
||||
} else {
|
||||
c.circularBitmapDrawable(config, itm.getIcon(c), holder.mView.itemImage)
|
||||
}
|
||||
|
||||
holder.mView.sourceTitle.text = itm.title
|
||||
holder.mView.sourceTitle.text = itm.getTitleDecoded()
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = items.size
|
||||
|
@ -28,17 +28,17 @@ class ParsedContent(
|
||||
}
|
||||
|
||||
constructor(source: Parcel) : this(
|
||||
title = source.readString(),
|
||||
title = source.readString().orEmpty(),
|
||||
content = source.readString(),
|
||||
date_published = source.readString(),
|
||||
date_published = source.readString().orEmpty(),
|
||||
lead_image_url = source.readString(),
|
||||
dek = source.readString(),
|
||||
url = source.readString(),
|
||||
domain = source.readString(),
|
||||
excerpt = source.readString(),
|
||||
dek = source.readString().orEmpty(),
|
||||
url = source.readString().orEmpty(),
|
||||
domain = source.readString().orEmpty(),
|
||||
excerpt = source.readString().orEmpty(),
|
||||
total_pages = source.readInt(),
|
||||
rendered_pages = source.readInt(),
|
||||
next_page_url = source.readString()
|
||||
next_page_url = source.readString().orEmpty()
|
||||
)
|
||||
|
||||
override fun describeContents() = 0
|
||||
|
@ -4,9 +4,15 @@ import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.text.Html
|
||||
import android.webkit.URLUtil
|
||||
import org.jsoup.Jsoup
|
||||
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
private fun constructUrl(config: Config?, path: String, file: String?): String {
|
||||
@ -58,6 +64,10 @@ data class Source(
|
||||
}
|
||||
return constructUrl(config, "favicons", icon)
|
||||
}
|
||||
|
||||
fun getTitleDecoded(): String {
|
||||
return Html.fromHtml(title).toString()
|
||||
}
|
||||
}
|
||||
|
||||
data class Item(
|
||||
@ -67,8 +77,8 @@ data class Item(
|
||||
@SerializedName("content") val content: String,
|
||||
@SerializedName("unread") val unread: Boolean,
|
||||
@SerializedName("starred") var starred: Boolean,
|
||||
@SerializedName("thumbnail") val thumbnail: String,
|
||||
@SerializedName("icon") val icon: String,
|
||||
@SerializedName("thumbnail") val thumbnail: String?,
|
||||
@SerializedName("icon") val icon: String?,
|
||||
@SerializedName("link") val link: String,
|
||||
@SerializedName("sourcetitle") val sourcetitle: String,
|
||||
@SerializedName("tags") val tags: SelfossTagType
|
||||
@ -84,17 +94,17 @@ data class Item(
|
||||
}
|
||||
|
||||
constructor(source: Parcel) : this(
|
||||
id = source.readString(),
|
||||
datetime = source.readString(),
|
||||
title = source.readString(),
|
||||
content = source.readString(),
|
||||
id = source.readString().orEmpty(),
|
||||
datetime = source.readString().orEmpty(),
|
||||
title = source.readString().orEmpty(),
|
||||
content = source.readString().orEmpty(),
|
||||
unread = 0.toByte() != source.readByte(),
|
||||
starred = 0.toByte() != source.readByte(),
|
||||
thumbnail = source.readString(),
|
||||
icon = source.readString(),
|
||||
link = source.readString(),
|
||||
sourcetitle = source.readString(),
|
||||
tags = source.readParcelable(ClassLoader.getSystemClassLoader())
|
||||
link = source.readString().orEmpty(),
|
||||
sourcetitle = source.readString().orEmpty(),
|
||||
tags = if (source.readParcelable<SelfossTagType>(ClassLoader.getSystemClassLoader()) != null) source.readParcelable(ClassLoader.getSystemClassLoader())!! else SelfossTagType("")
|
||||
)
|
||||
|
||||
override fun describeContents() = 0
|
||||
@ -127,6 +137,51 @@ data class Item(
|
||||
return constructUrl(config, "thumbnails", thumbnail)
|
||||
}
|
||||
|
||||
fun getImages() : ArrayList<String> {
|
||||
var allImages = ArrayList<String>()
|
||||
|
||||
for ( image in Jsoup.parse(content).getElementsByTag("img")) {
|
||||
val url = image.attr("src")
|
||||
if (url.toLowerCase().contains(".jpg") ||
|
||||
url.toLowerCase().contains(".jpeg") ||
|
||||
url.toLowerCase().contains(".png") ||
|
||||
url.toLowerCase().contains(".webp"))
|
||||
{
|
||||
allImages.add(url)
|
||||
}
|
||||
}
|
||||
return allImages
|
||||
}
|
||||
|
||||
fun preloadImages(context: Context) : Boolean {
|
||||
val imageUrls = this.getImages()
|
||||
|
||||
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL).timeout(10000)
|
||||
|
||||
|
||||
try {
|
||||
for (url in imageUrls) {
|
||||
if ( URLUtil.isValidUrl(url)) {
|
||||
val image = Glide.with(context).asBitmap()
|
||||
.apply(glideOptions)
|
||||
.load(url).submit()
|
||||
}
|
||||
}
|
||||
} catch (e : Error) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun getTitleDecoded(): String {
|
||||
return Html.fromHtml(title).toString()
|
||||
}
|
||||
|
||||
fun getSourceTitle(): String {
|
||||
return Html.fromHtml(sourcetitle).toString()
|
||||
}
|
||||
|
||||
// TODO: maybe find a better way to handle these kind of urls
|
||||
fun getLinkDecoded(): String {
|
||||
var stringUrl: String
|
||||
@ -168,7 +223,7 @@ data class SelfossTagType(val tags: String) : Parcelable {
|
||||
}
|
||||
|
||||
constructor(source: Parcel) : this(
|
||||
tags = source.readString()
|
||||
tags = source.readString().orEmpty()
|
||||
)
|
||||
|
||||
override fun describeContents() = 0
|
||||
|
@ -19,6 +19,7 @@ import apps.amine.bou.readerforselfoss.persistence.database.AppDatabase
|
||||
import apps.amine.bou.readerforselfoss.persistence.entities.ActionEntity
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_1_2
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_2_3
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_3_4
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible
|
||||
import apps.amine.bou.readerforselfoss.utils.persistence.toEntity
|
||||
@ -56,13 +57,13 @@ class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(con
|
||||
db = Room.databaseBuilder(
|
||||
applicationContext,
|
||||
AppDatabase::class.java, "selfoss-database"
|
||||
).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).build()
|
||||
).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).addMigrations(MIGRATION_3_4).build()
|
||||
|
||||
val api = SelfossApi(
|
||||
this.context,
|
||||
null,
|
||||
settings.getBoolean("isSelfSignedCert", false),
|
||||
sharedPref.getString("api_timeout", "-1").toLong()
|
||||
sharedPref.getString("api_timeout", "-1")!!.toLong()
|
||||
)
|
||||
|
||||
api.allItems().enqueue(object : Callback<List<Item>> {
|
||||
@ -104,6 +105,7 @@ class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(con
|
||||
notificationManager.notify(2, newItemsNotification.build())
|
||||
}
|
||||
}
|
||||
apiItems.map {it.preloadImages(context)}
|
||||
}
|
||||
Timer("", false).schedule(4000) {
|
||||
notificationManager.cancel(1)
|
||||
|
@ -1,28 +1,28 @@
|
||||
package apps.amine.bou.readerforselfoss.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.TypedArray
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.view.InflateException
|
||||
import android.view.*
|
||||
import android.webkit.*
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebSettings
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.room.Room
|
||||
import apps.amine.bou.readerforselfoss.ImageActivity
|
||||
import apps.amine.bou.readerforselfoss.R
|
||||
import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi
|
||||
import apps.amine.bou.readerforselfoss.api.mercury.ParsedContent
|
||||
@ -33,11 +33,13 @@ import apps.amine.bou.readerforselfoss.persistence.database.AppDatabase
|
||||
import apps.amine.bou.readerforselfoss.persistence.entities.ActionEntity
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_1_2
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_2_3
|
||||
import apps.amine.bou.readerforselfoss.persistence.migrations.MIGRATION_3_4
|
||||
import apps.amine.bou.readerforselfoss.themes.AppColors
|
||||
import apps.amine.bou.readerforselfoss.utils.Config
|
||||
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
|
||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
|
||||
import apps.amine.bou.readerforselfoss.utils.glide.loadMaybeBasicAuth
|
||||
import apps.amine.bou.readerforselfoss.utils.glide.getBitmapInputStream
|
||||
import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString
|
||||
import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible
|
||||
import apps.amine.bou.readerforselfoss.utils.openItemUrl
|
||||
@ -45,6 +47,7 @@ import apps.amine.bou.readerforselfoss.utils.shareLink
|
||||
import apps.amine.bou.readerforselfoss.utils.sourceAndDateText
|
||||
import apps.amine.bou.readerforselfoss.utils.succeeded
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.github.rubensousa.floatingtoolbar.FloatingToolbar
|
||||
import kotlinx.android.synthetic.main.fragment_article.view.*
|
||||
@ -53,6 +56,8 @@ import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
import java.util.concurrent.ExecutionException
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class ArticleFragment : Fragment() {
|
||||
@ -65,6 +70,7 @@ class ArticleFragment : Fragment() {
|
||||
private lateinit var contentSource: String
|
||||
private lateinit var contentImage: String
|
||||
private lateinit var contentTitle: String
|
||||
private lateinit var allImages : ArrayList<String>
|
||||
private lateinit var editor: SharedPreferences.Editor
|
||||
private lateinit var fab: FloatingActionButton
|
||||
private lateinit var appColors: AppColors
|
||||
@ -94,12 +100,12 @@ class ArticleFragment : Fragment() {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
pageNumber = arguments!!.getInt(ARG_POSITION)
|
||||
allItems = arguments!!.getParcelableArrayList(ARG_ITEMS)
|
||||
allItems = arguments!!.getParcelableArrayList<Item>(ARG_ITEMS) as ArrayList<Item>
|
||||
|
||||
db = Room.databaseBuilder(
|
||||
context!!,
|
||||
AppDatabase::class.java, "selfoss-database"
|
||||
).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).build()
|
||||
).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).addMigrations(MIGRATION_3_4).build()
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
@ -113,15 +119,16 @@ class ArticleFragment : Fragment() {
|
||||
|
||||
url = allItems[pageNumber.toInt()].getLinkDecoded()
|
||||
contentText = allItems[pageNumber.toInt()].content
|
||||
contentTitle = allItems[pageNumber.toInt()].title
|
||||
contentTitle = allItems[pageNumber.toInt()].getTitleDecoded()
|
||||
contentImage = allItems[pageNumber.toInt()].getThumbnail(activity!!)
|
||||
contentSource = allItems[pageNumber.toInt()].sourceAndDateText()
|
||||
allImages = allItems[pageNumber.toInt()].getImages()
|
||||
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
editor = prefs.edit()
|
||||
fontSize = prefs.getString("reader_font_size", "16").toInt()
|
||||
fontSize = prefs.getString("reader_font_size", "16")!!.toInt()
|
||||
|
||||
font = prefs.getString("reader_font", "")
|
||||
font = prefs.getString("reader_font", "")!!
|
||||
if (font.isNotEmpty()) {
|
||||
resId = context!!.resources.getIdentifier(font, "font", context!!.packageName)
|
||||
typeface = try {
|
||||
@ -141,7 +148,7 @@ class ArticleFragment : Fragment() {
|
||||
context!!,
|
||||
activity!!,
|
||||
settings.getBoolean("isSelfSignedCert", false),
|
||||
prefs.getString("api_timeout", "-1").toLong()
|
||||
prefs.getString("api_timeout", "-1")!!.toLong()
|
||||
)
|
||||
|
||||
fab = rootView!!.fab
|
||||
@ -410,6 +417,47 @@ class ArticleFragment : Fragment() {
|
||||
rootView!!.webcontent.settings.loadWithOverviewMode = true
|
||||
rootView!!.webcontent.settings.javaScriptEnabled = false
|
||||
|
||||
rootView!!.webcontent.webViewClient = object : WebViewClient() {
|
||||
override fun shouldOverrideUrlLoading(view: WebView?, url : String): Boolean {
|
||||
if (rootView!!.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
|
||||
rootView!!.context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun shouldInterceptRequest(view: WebView?, url: String): WebResourceResponse? {
|
||||
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
|
||||
if (url.toLowerCase().contains(".jpg") || url.toLowerCase().contains(".jpeg")) {
|
||||
try {
|
||||
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
|
||||
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.JPEG))
|
||||
}catch ( e : ExecutionException) {}
|
||||
}
|
||||
else if (url.toLowerCase().contains(".png")) {
|
||||
try {
|
||||
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
|
||||
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.PNG))
|
||||
}catch ( e : ExecutionException) {}
|
||||
}
|
||||
else if (url.toLowerCase().contains(".webp")) {
|
||||
try {
|
||||
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
|
||||
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.WEBP))
|
||||
}catch ( e : ExecutionException) {}
|
||||
}
|
||||
|
||||
return super.shouldInterceptRequest(view, url)
|
||||
}
|
||||
}
|
||||
|
||||
val gestureDetector = GestureDetector(activity, object : GestureDetector.SimpleOnGestureListener() {
|
||||
override fun onSingleTapUp(e: MotionEvent?): Boolean {
|
||||
return performClick()
|
||||
}
|
||||
})
|
||||
|
||||
rootView!!.webcontent.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event)}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
rootView!!.webcontent.settings.layoutAlgorithm =
|
||||
WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING
|
||||
@ -525,5 +573,20 @@ class ArticleFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
fun performClick(): Boolean {
|
||||
if (rootView!!.webcontent.hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE ||
|
||||
rootView!!.webcontent.hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
|
||||
|
||||
val position : Int = allImages.indexOf(rootView!!.webcontent.hitTestResult.extra)
|
||||
|
||||
val intent = Intent(activity, ImageActivity::class.java)
|
||||
intent.putExtra("allImages", allImages)
|
||||
intent.putExtra("position", position)
|
||||
startActivity(intent)
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
package apps.amine.bou.readerforselfoss.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import androidx.fragment.app.Fragment
|
||||
import apps.amine.bou.readerforselfoss.R
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import kotlinx.android.synthetic.main.fragment_image.view.*
|
||||
|
||||
class ImageFragment : Fragment() {
|
||||
|
||||
private lateinit var imageUrl : String
|
||||
private val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
imageUrl = requireArguments().getString("imageUrl")!!
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val view : View = inflater.inflate(R.layout.fragment_image, container, false)
|
||||
|
||||
view.photoView.visibility = View.VISIBLE
|
||||
Glide.with(activity)
|
||||
.asBitmap()
|
||||
.apply(glideOptions)
|
||||
.load(imageUrl)
|
||||
.into(view.photoView)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ARG_IMAGE = "imageUrl"
|
||||
|
||||
fun newInstance(
|
||||
imageUrl : String
|
||||
): ImageFragment {
|
||||
val fragment = ImageFragment()
|
||||
val args = Bundle()
|
||||
args.putString(ARG_IMAGE, imageUrl)
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import apps.amine.bou.readerforselfoss.persistence.entities.ItemEntity
|
||||
import apps.amine.bou.readerforselfoss.persistence.entities.SourceEntity
|
||||
import apps.amine.bou.readerforselfoss.persistence.entities.TagEntity
|
||||
|
||||
@Database(entities = [TagEntity::class, SourceEntity::class, ItemEntity::class, ActionEntity::class], version = 3)
|
||||
@Database(entities = [TagEntity::class, SourceEntity::class, ItemEntity::class, ActionEntity::class], version = 4)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun drawerDataDao(): DrawerDataDao
|
||||
|
||||
|
@ -20,9 +20,9 @@ data class ItemEntity(
|
||||
@ColumnInfo(name = "starred")
|
||||
var starred: Boolean,
|
||||
@ColumnInfo(name = "thumbnail")
|
||||
val thumbnail: String,
|
||||
val thumbnail: String?,
|
||||
@ColumnInfo(name = "icon")
|
||||
val icon: String,
|
||||
val icon: String?,
|
||||
@ColumnInfo(name = "link")
|
||||
val link: String,
|
||||
@ColumnInfo(name = "sourcetitle")
|
||||
|
@ -14,3 +14,21 @@ val MIGRATION_2_3: Migration = object : Migration(2, 3) {
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `actions` (`id` INTEGER NOT NULL, `articleid` TEXT NOT NULL, `read` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `unstarred` INTEGER NOT NULL, PRIMARY KEY(`id`))")
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_3_4: Migration = object : Migration(3, 4) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// @see https://stackoverflow.com/questions/57392015/how-to-migrate-not-null-table-column-into-null-in-android-room-database
|
||||
// Create the new table
|
||||
database.execSQL("CREATE TABLE IF NOT EXISTS `itemstmp` (`id` TEXT NOT NULL, `datetime` TEXT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `unread` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `thumbnail` TEXT, `icon` TEXT, `link` TEXT NOT NULL, `sourcetitle` TEXT NOT NULL, `tags` TEXT NOT NULL, PRIMARY KEY(`id`))")
|
||||
|
||||
// Copy the data
|
||||
database.execSQL(
|
||||
"INSERT INTO itemstmp (`id`, `datetime`, `title`, `content`, `unread`, `starred`, `thumbnail`, `icon`, `link`, `sourcetitle`, `tags`) SELECT `id`, `datetime`, `title`, `content`, `unread`, `starred`, `thumbnail`, `icon`, `link`, `sourcetitle`, `tags` FROM items")
|
||||
|
||||
// Remove the old table
|
||||
database.execSQL("DROP TABLE items")
|
||||
|
||||
// Change the table name to the correct one
|
||||
database.execSQL("ALTER TABLE itemstmp RENAME TO items")
|
||||
}
|
||||
}
|
||||
|
@ -195,16 +195,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
getActivity().finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
@ -245,16 +235,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
getActivity().finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -298,16 +278,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
getActivity().finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
@ -322,10 +292,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
getActivity().finish();
|
||||
return true;
|
||||
} else if (id == R.id.clear) {
|
||||
if (id == R.id.clear) {
|
||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
SharedPreferences.Editor editor = pref.edit();
|
||||
editor.remove("color_primary");
|
||||
@ -334,7 +301,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
editor.remove("color_accent_dark");
|
||||
editor.remove("dark_theme");
|
||||
editor.apply();
|
||||
getActivity().finish();
|
||||
getActivity().recreate();
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@ -353,16 +320,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
addPreferencesFromResource(R.xml.pref_offline);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
getActivity().finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
@ -373,16 +330,6 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
addPreferencesFromResource(R.xml.pref_experimental);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
getActivity().finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -390,7 +337,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
finish();
|
||||
super.onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
|
@ -18,6 +18,7 @@ class AppColors(a: Activity) {
|
||||
@ColorInt val colorAccentDark: Int
|
||||
@ColorInt val cardBackgroundColor: Int
|
||||
@ColorInt val colorBackground: Int
|
||||
@ColorInt val textColor: Int
|
||||
val isDarkTheme: Boolean
|
||||
|
||||
init {
|
||||
@ -57,6 +58,12 @@ class AppColors(a: Activity) {
|
||||
android.R.color.background_light
|
||||
}
|
||||
|
||||
textColor = if (isDarkTheme) {
|
||||
R.color.md_white_1000
|
||||
} else {
|
||||
R.color.md_grey_900
|
||||
}
|
||||
|
||||
val wrapper = Context::class.java
|
||||
val method = wrapper!!.getMethod("getThemeResId")
|
||||
method.isAccessible = true
|
||||
|
@ -11,19 +11,19 @@ class Config(c: Context) {
|
||||
val settings: SharedPreferences = c.getSharedPreferences(settingsName, Context.MODE_PRIVATE)
|
||||
|
||||
val baseUrl: String
|
||||
get() = settings.getString("url", "")
|
||||
get() = settings.getString("url", "")!!
|
||||
|
||||
val userLogin: String
|
||||
get() = settings.getString("login", "")
|
||||
get() = settings.getString("login", "")!!
|
||||
|
||||
val userPassword: String
|
||||
get() = settings.getString("password", "")
|
||||
get() = settings.getString("password", "")!!
|
||||
|
||||
val httpUserLogin: String
|
||||
get() = settings.getString("httpUserName", "")
|
||||
get() = settings.getString("httpUserName", "")!!
|
||||
|
||||
val httpUserPassword: String
|
||||
get() = settings.getString("httpPassword", "")
|
||||
get() = settings.getString("httpPassword", "")!!
|
||||
|
||||
companion object {
|
||||
const val settingsName = "paramsselfoss"
|
||||
|
@ -32,7 +32,7 @@ fun Item.sourceAndDateText(): String {
|
||||
""
|
||||
}
|
||||
|
||||
return this.sourcetitle + formattedDate
|
||||
return this.getSourceTitle() + formattedDate
|
||||
}
|
||||
|
||||
fun Item.toggleStar(): Item {
|
||||
|
@ -14,6 +14,9 @@ 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) =
|
||||
Glide.with(this)
|
||||
@ -56,4 +59,11 @@ fun RequestManager.loadMaybeBasicAuth(config: Config, url: String): RequestBuild
|
||||
}
|
||||
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)
|
||||
val bitmapData: ByteArray = byteArrayOutputStream.toByteArray()
|
||||
return ByteArrayInputStream(bitmapData)
|
||||
}
|
@ -28,7 +28,7 @@ fun SourceEntity.toView(): Source =
|
||||
fun Source.toEntity(): SourceEntity =
|
||||
SourceEntity(
|
||||
this.id,
|
||||
this.title,
|
||||
this.getTitleDecoded(),
|
||||
this.tags.tags,
|
||||
this.spout,
|
||||
this.error,
|
||||
@ -61,13 +61,13 @@ fun Item.toEntity(): ItemEntity =
|
||||
ItemEntity(
|
||||
this.id,
|
||||
this.datetime,
|
||||
this.title,
|
||||
this.getTitleDecoded(),
|
||||
this.content,
|
||||
this.unread,
|
||||
this.starred,
|
||||
this.thumbnail,
|
||||
this.icon,
|
||||
this.link,
|
||||
this.sourcetitle,
|
||||
this.getSourceTitle(),
|
||||
this.tags.tags
|
||||
)
|
33
app/src/main/res/layout/activity_image.xml
Normal file
33
app/src/main/res/layout/activity_image.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:popupTheme="?attr/toolbarPopupTheme"
|
||||
app:theme="@style/ToolBarStyle" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/appBarLayout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
16
app/src/main/res/layout/fragment_image.xml
Normal file
16
app/src/main/res/layout/fragment_image.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.github.chrisbanes.photoview.PhotoView
|
||||
android:id="@+id/photoView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="@android:color/black"
|
||||
app:srcCompat="@android:drawable/screen_background_dark" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@ -3,14 +3,14 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="88dp">
|
||||
|
||||
android:layout_height="88dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemImage"
|
||||
android:layout_width="88dp"
|
||||
android:layout_height="88dp"
|
||||
android:layout_width="46dp"
|
||||
android:layout_height="46dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="21dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@ -18,9 +18,9 @@
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="start"
|
||||
@ -39,16 +39,17 @@
|
||||
android:id="@+id/sourceTitleAndDate"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="66dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:gravity="start"
|
||||
android:maxLines="1"
|
||||
android:textAlignment="viewStart"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/itemImage"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Google Actualité Il y a 5h" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Lector per a Selfoss"</string>
|
||||
<string name="title_activity_login">"Inicia la sessió"</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Reader für selfoss"</string>
|
||||
<string name="title_activity_login">"Anmelden"</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Lector para Selfoss"</string>
|
||||
<string name="title_activity_login">"Iniciar sesión"</string>
|
||||
|
163
app/src/main/res/values-fa-rIR/strings.xml
Normal file
163
app/src/main/res/values-fa-rIR/strings.xml
Normal file
@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<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>
|
||||
<string name="title_activity_settings">"Settings"</string>
|
||||
<string name="pref_header_general">"General"</string>
|
||||
<string name="add_source_hint_tags">"Tag1, Tag2, Tag3"</string>
|
||||
<string name="add_source_hint_url">"Link"</string>
|
||||
<string name="add_source_hint_name">"Name"</string>
|
||||
<string name="add_source">"Add a source"</string>
|
||||
<string name="add_source_save">"Save"</string>
|
||||
<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>
|
||||
<string name="tab_favs">"Favorites"</string>
|
||||
<string name="action_about">"About"</string>
|
||||
<string name="marked_as_read">"Item read"</string>
|
||||
<string name="marked_as_unread">"Item unread"</string>
|
||||
<string name="undo_string">"Undo"</string>
|
||||
<string name="addStringNoUrl">"Log in to add sources."</string>
|
||||
<string name="cant_get_sources">"Can't get sources list."</string>
|
||||
<string name="cant_create_source">"Can't create source."</string>
|
||||
<string name="cant_get_spouts">"Can't get spouts list."</string>
|
||||
<string name="form_not_complete">"The form is not complete"</string>
|
||||
<string name="pref_header_links">"Links"</string>
|
||||
<string name="issue_tracker_link">"Issue Tracker"</string>
|
||||
<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>
|
||||
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
||||
<string name="pref_general_internal_browser_title">"Open links inside the app"</string>
|
||||
<string name="pref_general_internal_browser_on">"Articles will open inside the app"</string>
|
||||
<string name="pref_general_internal_browser_off">"Articles will open with your default browser"</string>
|
||||
<string name="prefer_article_viewer_title">"Use the article viewer"</string>
|
||||
<string name="prefer_article_viewer_on">"Will use the article viewer instead of the internal browser"</string>
|
||||
<string name="prefer_article_viewer_off">"Will use the internal browser instead of the article viewer"</string>
|
||||
<string name="pref_general_category_links">"Link handling"</string>
|
||||
<string name="pref_general_category_displaying">"Displaying"</string>
|
||||
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
||||
<string name="pref_switch_card_view_off">"The articles will be displayed as a list"</string>
|
||||
<string name="menu_home_refresh">"Update remote"</string>
|
||||
<string name="refresh_success_response">"The remote is updated, you can now reload the articles list"</string>
|
||||
<string name="refresh_failer_message">"The update didn't work, try again later, or check your selfoss logs."</string>
|
||||
<string name="refresh_in_progress">"Refresh in progress"</string>
|
||||
<string name="card_height_title">Full height cards</string>
|
||||
<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>
|
||||
<string name="base_url_error">There was an issue when trying to communicate with your Selfoss Instance. If the issue persists, please get in touch with me.</string>
|
||||
<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>
|
||||
<string name="drawer_report_bug">Report a bug</string>
|
||||
<string name="items_number_should_be_number">The items number should be an integer.</string>
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<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>
|
||||
<string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string>
|
||||
<string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string>
|
||||
<string name="pref_switch_items_caching">Save items for offline use</string>
|
||||
<string name="no_network_connectivity">Not connected !</string>
|
||||
<string name="pref_switch_periodic_refresh">Sync articles</string>
|
||||
<string name="pref_switch_periodic_refresh_off">Articles will not be synced in the background</string>
|
||||
<string name="pref_switch_periodic_refresh_on">Articles will periodically be synced</string>
|
||||
<string name="pref_periodic_refresh_minutes_title"><![CDATA[Sync interval ( >= 15 minutes)]]></string>
|
||||
<string name="pref_switch_refresh_when_charging">Only refresh when phone is charging</string>
|
||||
<string name="loading_notification_title">Loading ...</string>
|
||||
<string name="loading_notification_text">Selfoss is syncing your articles</string>
|
||||
<string name="notification_channel_sync">Sync notification</string>
|
||||
<string name="new_items_channel_sync">New items notification</string>
|
||||
<string name="new_items_notification_title">New items !</string>
|
||||
<string name="new_items_notification_text">%1$d new items loaded.</string>
|
||||
<string name="pref_switch_notify_new_items">Notify on new items synced.</string>
|
||||
<string name="shortcut_offline">Offline</string>
|
||||
<string name="pref_api_timeout">Api Timeout</string>
|
||||
<string name="pref_header_experimental">Experimental</string>
|
||||
<string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
|
||||
<string name="webview_dialog_issue_title">Webview issue</string>
|
||||
<string name="reader_text_align_left">Align left</string>
|
||||
<string name="reader_text_align_justify">Justify</string>
|
||||
<string name="settings_reader_font">Reader font</string>
|
||||
</resources>
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Reader for Selfoss"</string>
|
||||
<string name="title_activity_login">"Login"</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Lector para Selfoss"</string>
|
||||
<string name="title_activity_login">"Acceder"</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Reader for Selfoss"</string>
|
||||
<string name="title_activity_login">"Masuk"</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Lettore RSS per Selfoss"</string>
|
||||
<string name="title_activity_login">"Accedi"</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Reader for Selfoss"</string>
|
||||
<string name="title_activity_login">"로그인"</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Selfoss Reader"</string>
|
||||
<string name="title_activity_login">"Inloggen"</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Reader for Selfoss"</string>
|
||||
<string name="title_activity_login">"Entrar"</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Leitor para Selfoss"</string>
|
||||
<string name="title_activity_login">"Iniciar sessão"</string>
|
||||
|
163
app/src/main/res/values-si-rLK/strings.xml
Normal file
163
app/src/main/res/values-si-rLK/strings.xml
Normal file
@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<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>
|
||||
<string name="title_activity_settings">"සැකසුම්"</string>
|
||||
<string name="pref_header_general">"General"</string>
|
||||
<string name="add_source_hint_tags">"Tag1, Tag2, Tag3"</string>
|
||||
<string name="add_source_hint_url">"Link"</string>
|
||||
<string name="add_source_hint_name">"නම"</string>
|
||||
<string name="add_source">"Add a source"</string>
|
||||
<string name="add_source_save">"සුරකින්න"</string>
|
||||
<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>
|
||||
<string name="tab_favs">"Favorites"</string>
|
||||
<string name="action_about">"මේ ගැන"</string>
|
||||
<string name="marked_as_read">"Item read"</string>
|
||||
<string name="marked_as_unread">"Item unread"</string>
|
||||
<string name="undo_string">"Undo"</string>
|
||||
<string name="addStringNoUrl">"Log in to add sources."</string>
|
||||
<string name="cant_get_sources">"Can't get sources list."</string>
|
||||
<string name="cant_create_source">"Can't create source."</string>
|
||||
<string name="cant_get_spouts">"Can't get spouts list."</string>
|
||||
<string name="form_not_complete">"The form is not complete"</string>
|
||||
<string name="pref_header_links">"Links"</string>
|
||||
<string name="issue_tracker_link">"Issue Tracker"</string>
|
||||
<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>
|
||||
<string name="text_wrong_url">"You seem to be trying to use an invalid URL. Make sure it is correct, and if the problem persists, contact me (via the store contact link). Please note that the app needs you to be using Selfoss. You can't access RSS feeds without it."</string>
|
||||
<string name="pref_general_internal_browser_title">"Open links inside the app"</string>
|
||||
<string name="pref_general_internal_browser_on">"Articles will open inside the app"</string>
|
||||
<string name="pref_general_internal_browser_off">"Articles will open with your default browser"</string>
|
||||
<string name="prefer_article_viewer_title">"Use the article viewer"</string>
|
||||
<string name="prefer_article_viewer_on">"Will use the article viewer instead of the internal browser"</string>
|
||||
<string name="prefer_article_viewer_off">"Will use the internal browser instead of the article viewer"</string>
|
||||
<string name="pref_general_category_links">"Link handling"</string>
|
||||
<string name="pref_general_category_displaying">"Displaying"</string>
|
||||
<string name="pref_switch_card_view_on">"The articles will be displayed as cards"</string>
|
||||
<string name="pref_switch_card_view_off">"The articles will be displayed as a list"</string>
|
||||
<string name="menu_home_refresh">"Update remote"</string>
|
||||
<string name="refresh_success_response">"The remote is updated, you can now reload the articles list"</string>
|
||||
<string name="refresh_failer_message">"The update didn't work, try again later, or check your selfoss logs."</string>
|
||||
<string name="refresh_in_progress">"Refresh in progress"</string>
|
||||
<string name="card_height_title">Full height cards</string>
|
||||
<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>
|
||||
<string name="base_url_error">There was an issue when trying to communicate with your Selfoss Instance. If the issue persists, please get in touch with me.</string>
|
||||
<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>
|
||||
<string name="drawer_report_bug">Report a bug</string>
|
||||
<string name="items_number_should_be_number">The items number should be an integer.</string>
|
||||
<string name="reader_action_more">Read more</string>
|
||||
<string name="reader_action_open">Open in browser</string>
|
||||
<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>
|
||||
<string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string>
|
||||
<string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string>
|
||||
<string name="pref_switch_items_caching">Save items for offline use</string>
|
||||
<string name="no_network_connectivity">Not connected !</string>
|
||||
<string name="pref_switch_periodic_refresh">Sync articles</string>
|
||||
<string name="pref_switch_periodic_refresh_off">Articles will not be synced in the background</string>
|
||||
<string name="pref_switch_periodic_refresh_on">Articles will periodically be synced</string>
|
||||
<string name="pref_periodic_refresh_minutes_title"><![CDATA[Sync interval ( >= 15 minutes)]]></string>
|
||||
<string name="pref_switch_refresh_when_charging">Only refresh when phone is charging</string>
|
||||
<string name="loading_notification_title">Loading ...</string>
|
||||
<string name="loading_notification_text">Selfoss is syncing your articles</string>
|
||||
<string name="notification_channel_sync">Sync notification</string>
|
||||
<string name="new_items_channel_sync">New items notification</string>
|
||||
<string name="new_items_notification_title">New items !</string>
|
||||
<string name="new_items_notification_text">%1$d new items loaded.</string>
|
||||
<string name="pref_switch_notify_new_items">Notify on new items synced.</string>
|
||||
<string name="shortcut_offline">Offline</string>
|
||||
<string name="pref_api_timeout">Api Timeout</string>
|
||||
<string name="pref_header_experimental">Experimental</string>
|
||||
<string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
|
||||
<string name="webview_dialog_issue_title">Webview issue</string>
|
||||
<string name="reader_text_align_left">Align left</string>
|
||||
<string name="reader_text_align_justify">Justify</string>
|
||||
<string name="settings_reader_font">Reader font</string>
|
||||
</resources>
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Selfoss için okuyucu"</string>
|
||||
<string name="title_activity_login">"Giriş"</string>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Selfoss 阅读器"</string>
|
||||
<string name="title_activity_login">"登录"</string>
|
||||
@ -36,7 +35,7 @@
|
||||
<string name="tab_favs">"收藏夹"</string>
|
||||
<string name="action_about">"关于我们"</string>
|
||||
<string name="marked_as_read">"已读"</string>
|
||||
<string name="marked_as_unread">"Item unread"</string>
|
||||
<string name="marked_as_unread">"未读条目"</string>
|
||||
<string name="undo_string">"撤销"</string>
|
||||
<string name="addStringNoUrl">"登录以添加数据源。"</string>
|
||||
<string name="cant_get_sources">"无法获取数据列表。"</string>
|
||||
@ -84,7 +83,7 @@
|
||||
<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="cant_mark_unread">无法将文章标记为未读</string>
|
||||
<string name="drawer_error_loading_tags">加载标记时出错..。</string>
|
||||
<string name="drawer_error_loading_sources">加载源时出错..。</string>
|
||||
<string name="drawer_item_filters">搜索条件</string>
|
||||
@ -106,7 +105,7 @@
|
||||
<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="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>
|
||||
@ -122,43 +121,43 @@
|
||||
<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">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">這會使全部項目標示為已讀</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">自动发送錯誤报告</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">错误报告</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>
|
||||
<string name="pref_switch_items_caching_off">Articles won\'t be saved to the device memory, and the app won\'t be usable offline.</string>
|
||||
<string name="pref_switch_items_caching_on">Articles will be saved to the device memory and will be used for offline use.</string>
|
||||
<string name="pref_switch_items_caching">Save items for offline use</string>
|
||||
<string name="no_network_connectivity">未连接</string>
|
||||
<string name="pref_switch_periodic_refresh">Sync articles</string>
|
||||
<string name="pref_switch_periodic_refresh_off">Articles will not be synced in the background</string>
|
||||
<string name="pref_switch_periodic_refresh_on">Articles will periodically be synced</string>
|
||||
<string name="pref_periodic_refresh_minutes_title"><![CDATA[Sync interval ( >= 15 minutes)]]></string>
|
||||
<string name="pref_switch_refresh_when_charging">Only refresh when phone is charging</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>
|
||||
<string name="pref_switch_items_caching_off">文章不会被保存到设备内存,应用程序在离线时将无法阅读它们</string>
|
||||
<string name="pref_switch_items_caching_on">文章将被保存到设备内存并可在离线时使用</string>
|
||||
<string name="pref_switch_items_caching">保存项目以便离线使用</string>
|
||||
<string name="no_network_connectivity">未连接!</string>
|
||||
<string name="pref_switch_periodic_refresh">同步文章</string>
|
||||
<string name="pref_switch_periodic_refresh_off">文章将不会在后台同步</string>
|
||||
<string name="pref_switch_periodic_refresh_on">将定期同步文章</string>
|
||||
<string name="pref_periodic_refresh_minutes_title"><![CDATA[同步间隔 (>= 15分钟)]]></string>
|
||||
<string name="pref_switch_refresh_when_charging">仅在手机充电时刷新</string>
|
||||
<string name="loading_notification_title">加载中...</string>
|
||||
<string name="loading_notification_text">Selfoss is syncing your articles</string>
|
||||
<string name="loading_notification_text">Selfoss 正在同步您的文章</string>
|
||||
<string name="notification_channel_sync">同步通知</string>
|
||||
<string name="new_items_channel_sync">New items notification</string>
|
||||
<string name="new_items_notification_title">New items !</string>
|
||||
<string name="new_items_notification_text">%1$d new items loaded.</string>
|
||||
<string name="pref_switch_notify_new_items">Notify on new items synced.</string>
|
||||
<string name="shortcut_offline">Offline</string>
|
||||
<string name="pref_api_timeout">Api Timeout</string>
|
||||
<string name="pref_header_experimental">Experimental</string>
|
||||
<string name="webview_dialog_issue_message">Webview not available. Disabling the article viewer to avoid any future crashes. Will load articles inside of your browser from now on.</string>
|
||||
<string name="webview_dialog_issue_title">Webview issue</string>
|
||||
<string name="reader_text_align_left">Align left</string>
|
||||
<string name="reader_text_align_justify">Justify</string>
|
||||
<string name="settings_reader_font">Reader font</string>
|
||||
<string name="new_items_channel_sync">新条目通知</string>
|
||||
<string name="new_items_notification_title">新条目 !</string>
|
||||
<string name="new_items_notification_text">已加载%1$d新条目</string>
|
||||
<string name="pref_switch_notify_new_items">通知已同步的新条目</string>
|
||||
<string name="shortcut_offline">离线</string>
|
||||
<string name="pref_api_timeout">Api 超时</string>
|
||||
<string name="pref_header_experimental">实验性功能</string>
|
||||
<string name="webview_dialog_issue_message">Webview不可用。禁用文章查看器以避免将来发生崩溃。从现在起将在浏览器内加载文章。</string>
|
||||
<string name="webview_dialog_issue_title">Webview问题</string>
|
||||
<string name="reader_text_align_left">左对齐</string>
|
||||
<string name="reader_text_align_justify">左右对齐</string>
|
||||
<string name="settings_reader_font">阅读器字体</string>
|
||||
</resources>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">"Selfoss 阅读器"</string>
|
||||
<string name="title_activity_login">"登录"</string>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
kotlin_version = '1.3.31'
|
||||
kotlin_version = '1.4.21'
|
||||
android_version = '1.0.0'
|
||||
androidx_version = '1.1.0-alpha05'
|
||||
lifecycle_version = '2.2.0-alpha01'
|
||||
@ -17,7 +17,7 @@ buildscript {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
13
fastlane/metadata/android/en-US/full_description.txt
Normal file
13
fastlane/metadata/android/en-US/full_description.txt
Normal file
@ -0,0 +1,13 @@
|
||||
A new RSS reader for <a href="http://selfoss.aditu.de/">selfoss</a>.
|
||||
|
||||
What it does:
|
||||
|
||||
<ul>
|
||||
<li>Fetches read, unread, and favorite feeds.</li>
|
||||
<li>Marking as read, marking as favorite.</li>
|
||||
<li>Manage selfoss sources from the app.</li>
|
||||
<li>Add an RSS feed from within the app, or by sharing a link from your browser.</li>
|
||||
<li>Choose between multiple light and dark themes.</li>
|
||||
</ul>
|
||||
|
||||
PS: It only works with Selfoss
|
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 266 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 973 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 457 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 422 KiB |
3
fastlane/metadata/android/en-US/short_description.txt
Normal file
3
fastlane/metadata/android/en-US/short_description.txt
Normal file
@ -0,0 +1,3 @@
|
||||
A new RSS reader for <a href="http://selfoss.aditu.de/">selfoss</a>.
|
||||
|
||||
It connects to your selfoss instance (works only with selfoss, and can't work without it), and you'll be able to read and manage all your RSS feeds.
|
1
fastlane/metadata/android/en-US/title.txt
Normal file
1
fastlane/metadata/android/en-US/title.txt
Normal file
@ -0,0 +1 @@
|
||||
Reader for Selfoss
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Sat Feb 01 12:14:14 CET 2020
|
||||
#Sat Dec 12 19:38:31 CET 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
|
||||
|
Reference in New Issue
Block a user