Compare commits
	
		
			67 Commits
		
	
	
		
			b16f86dda1
			...
			v122102881
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 8b0bbe71c9 | ||
| 8bfe14c019 | |||
| 208babbce3 | |||
| 02098a7aa9 | |||
| d0a982f385 | |||
| 1d1c121aab | |||
| fe12819163 | |||
|  | 023a30c008 | ||
|  | a2862a2587 | ||
|  | 054e936657 | ||
| 1d2e5069b8 | |||
| a147646743 | |||
| 32e7fc0038 | |||
| c15bf44032 | |||
| 0bcd55bd4e | |||
| ebef0b3511 | |||
| 713ceb05bf | |||
| dc8381b661 | |||
| b5b820c64b | |||
| f7055626d9 | |||
|  | 6ec3e96909 | ||
| 22da30eaa8 | |||
| 79fd115f5e | |||
| 8dc3d319cd | |||
| 27bb056397 | |||
| f9ba13dc32 | |||
| 6f60ef4346 | |||
| 28b950f467 | |||
| a9c7ec3dc1 | |||
| 920d4ac1ef | |||
| 0e96d313ec | |||
| 7211fdb1a3 | |||
|  | 381d6acc82 | ||
| d311c2cdeb | |||
| 219cae5d74 | |||
| 2968aee309 | |||
| 6cb4b35c93 | |||
| 15ec0f2d26 | |||
| 4781e30da2 | |||
| c8759cc035 | |||
| cb4f2f02ef | |||
| 7517626ab7 | |||
| 41c951b659 | |||
|  | ad279c6683 | ||
|  | 5f0817ddb7 | ||
|  | 7124cbcacd | ||
|  | 2a710a1a08 | ||
|  | 82ec2445a1 | ||
|  | cabb6d494d | ||
|  | 5c12481813 | ||
| e2afff0b8e | |||
| a382fc89ea | |||
| 3f0a3903ae | |||
| f46f98cef0 | |||
| bf6f1a917e | |||
| 71c0a4d340 | |||
| 63c550ead3 | |||
| 366b2e10f1 | |||
| d2436bb976 | |||
| ef994460c1 | |||
| 758708e18d | |||
| c0381144d1 | |||
| cda3ba6cb4 | |||
| a4636cc0c8 | |||
| 60c24fc75a | |||
| 5853a19937 | |||
| 99f2c04bf6 | 
| @@ -5,7 +5,6 @@ name: test | ||||
| steps: | ||||
|   - name: AnylyseBuildTest | ||||
|     image: mingc/android-build-box:latest | ||||
|     failure: ignore | ||||
|     commands: | ||||
|       - echo "---------------------------------------------------------" | ||||
|       - echo "Analysing..." | ||||
| @@ -16,6 +15,7 @@ steps: | ||||
|       - echo "---------------------------------------------------------" | ||||
|       - echo "Testing..." | ||||
|       - echo "---------------------------------------------------------" | ||||
|       - ./gradlew test -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false | ||||
|     environment: | ||||
|       SONAR_HOST_URL: | ||||
|         from_secret: sonarScannerHostUrl | ||||
|   | ||||
| @@ -15,9 +15,6 @@ import androidx.activity.result.contract.ActivityResultContracts | ||||
| import androidx.appcompat.app.ActionBarDrawerToggle | ||||
| import androidx.appcompat.app.AlertDialog | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.appcompat.app.AppCompatDelegate | ||||
| import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO | ||||
| import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES | ||||
| import androidx.appcompat.widget.SearchView | ||||
| import androidx.core.view.doOnNextLayout | ||||
| import androidx.drawerlayout.widget.DrawerLayout | ||||
| @@ -92,15 +89,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar | ||||
|  | ||||
|     private val settingsLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { | ||||
|         appSettingsService.refreshUserSettings() | ||||
|         AppCompatDelegate.setDefaultNightMode(if (appSettingsService.isDarkThemeEnabled()) MODE_NIGHT_YES else MODE_NIGHT_NO) | ||||
|     } | ||||
|  | ||||
|     override val di by closestDI() | ||||
|     private val repository : Repository by instance() | ||||
|     private val appSettingsService : AppSettingsService by instance() | ||||
|  | ||||
|     data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?) | ||||
|  | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
|         binding = ActivityHomeBinding.inflate(layoutInflater) | ||||
| @@ -353,27 +347,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar | ||||
|         ) | ||||
|  | ||||
|         CoroutineScope(Dispatchers.IO).launch { | ||||
|             val drawerData = DrawerData(repository.getDBTags().map { it.toView() }, | ||||
|                                         repository.getDBSources().map { it.toView() }) | ||||
|             val tags = repository.getTags() | ||||
|             val sources = repository.getSources() | ||||
|             runOnUiThread { | ||||
|                 // Only refresh if there is no data in the DB, or if the `UpdateSources` setting is enabled | ||||
|                 if (drawerData.sources?.isEmpty() == true || appSettingsService.isUpdateSourcesEnabled()) { | ||||
|                     drawerApiCalls(drawerData) | ||||
|                 } else { | ||||
|                     handleDrawerData(drawerData, loadedFromCache = true) | ||||
|                 } | ||||
|                 handleDrawerData(tags, sources) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun drawerApiCalls(drawerData: DrawerData) { | ||||
|         CoroutineScope(Dispatchers.Main).launch { | ||||
|             val apiDrawerData = DrawerData(repository.getTags(), repository.getSources()) | ||||
|             handleDrawerData(if (drawerData != apiDrawerData) apiDrawerData else drawerData) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun handleDrawerData(drawerData: DrawerData, loadedFromCache: Boolean = false) { | ||||
|     private fun handleDrawerData(tags: List<SelfossModel.Tag>, sources: List<SelfossModel.Source>) { | ||||
|         binding.mainDrawer.itemAdapter.clear() | ||||
|  | ||||
|         // Filters title with clear action | ||||
| @@ -387,24 +369,24 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar | ||||
|         } | ||||
|  | ||||
|         // Hidden tags | ||||
|         if (drawerData.tags != null && drawerData.tags.isNotEmpty() && appSettingsService.getHiddenTags().isNotEmpty()) { | ||||
|         if (tags.isNotEmpty() && appSettingsService.getHiddenTags().isNotEmpty()) { | ||||
|             secondaryItem( | ||||
|                 withDivider = true, | ||||
|                 R.string.drawer_item_hidden_tags, | ||||
|                 DRAWER_ID_HIDDEN_TAGS | ||||
|             ) | ||||
|             handleHiddenTags(drawerData.tags) | ||||
|             handleHiddenTags(tags) | ||||
|         } | ||||
|  | ||||
|         // Tags | ||||
|         secondaryItem(withDivider = true, R.string.drawer_item_tags, DRAWER_ID_TAGS) | ||||
|         if (drawerData.tags == null && !loadedFromCache) { | ||||
|         if (tags.isEmpty()) { | ||||
|             binding.mainDrawer.itemAdapter.add( | ||||
|                 SecondaryDrawerItem() | ||||
|                     .apply { nameRes = R.string.drawer_error_loading_tags; isSelectable = false } | ||||
|             ) | ||||
|         } else { | ||||
|             handleTags(drawerData.tags!!) | ||||
|             handleTags(tags) | ||||
|         } | ||||
|  | ||||
|         // Sources | ||||
| @@ -412,15 +394,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar | ||||
|             startActivity(Intent(v!!.context, SourcesActivity::class.java)) | ||||
|             false | ||||
|         } | ||||
|         if (drawerData.sources == null && !loadedFromCache) { | ||||
|         if (sources.isEmpty()) { | ||||
|             binding.mainDrawer.itemAdapter.add( | ||||
|                 SecondaryDrawerItem().apply { | ||||
|                     nameRes = R.string.drawer_error_loading_tags | ||||
|                     nameRes = R.string.drawer_error_loading_sources | ||||
|                     isSelectable = false | ||||
|                 } | ||||
|             ) | ||||
|         } else { | ||||
|             handleSources(drawerData.sources!!) | ||||
|             handleSources(sources) | ||||
|         } | ||||
|  | ||||
|         // About action | ||||
|   | ||||
| @@ -38,7 +38,7 @@ class LoginActivity : AppCompatActivity(), DIAware { | ||||
|  | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
|         AppCompatDelegate.setDefaultNightMode(if (appSettingsService.isDarkThemeEnabled()) AppCompatDelegate.MODE_NIGHT_YES else AppCompatDelegate.MODE_NIGHT_NO) | ||||
|         AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) | ||||
|  | ||||
|         binding = ActivityLoginBinding.inflate(layoutInflater) | ||||
|         val view = binding.root | ||||
| @@ -163,7 +163,6 @@ class LoginActivity : AppCompatActivity(), DIAware { | ||||
|             CoroutineScope(Dispatchers.IO).launch { | ||||
|                 val result = repository.login() | ||||
|                 if (result) { | ||||
|                     repository.updateApiVersion() | ||||
|                     goToMain() | ||||
|                 } else { | ||||
|                     CoroutineScope(Dispatchers.Main).launch { | ||||
|   | ||||
| @@ -75,7 +75,6 @@ class MyApp : MultiDexApplication(), DIAware { | ||||
|                 ).show() | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     private fun handleNotificationChannels() { | ||||
|   | ||||
| @@ -28,7 +28,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte | ||||
|         updateItems(this.items) | ||||
|     } | ||||
|  | ||||
|     private fun unmarkSnackbar(position: Int) { | ||||
|     private fun unmarkSnackbar(item: SelfossModel.Item, position: Int) { | ||||
|         val s = Snackbar | ||||
|             .make( | ||||
|                 app.findViewById(R.id.coordLayout), | ||||
| @@ -37,7 +37,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte | ||||
|             ) | ||||
|             .setAction(R.string.undo_string) { | ||||
|                 CoroutineScope(Dispatchers.IO).launch { | ||||
|                     unreadItemAtIndex(position, false) | ||||
|                     unreadItemAtIndex(item, position, false) | ||||
|                 } | ||||
|             } | ||||
|  | ||||
| @@ -47,7 +47,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte | ||||
|         s.show() | ||||
|     } | ||||
|  | ||||
|     private fun markSnackbar(position: Int) { | ||||
|     private fun markSnackbar(item: SelfossModel.Item, position: Int) { | ||||
|         val s = Snackbar | ||||
|             .make( | ||||
|                 app.findViewById(R.id.coordLayout), | ||||
| @@ -55,7 +55,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte | ||||
|                 Snackbar.LENGTH_LONG | ||||
|             ) | ||||
|             .setAction(R.string.undo_string) { | ||||
|                 readItemAtIndex(position) | ||||
|                 readItemAtIndex(item, position, false) | ||||
|             } | ||||
|  | ||||
|         val view = s.view | ||||
| @@ -66,37 +66,36 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte | ||||
|  | ||||
|     fun handleItemAtIndex(position: Int) { | ||||
|         if (items[position].unread) { | ||||
|             readItemAtIndex(position) | ||||
|             readItemAtIndex(items[position], position) | ||||
|         } else { | ||||
|             unreadItemAtIndex(position) | ||||
|             unreadItemAtIndex(items[position], position) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun readItemAtIndex(position: Int, showSnackbar: Boolean = true) { | ||||
|         val i = items[position] | ||||
|     private fun readItemAtIndex(item: SelfossModel.Item, position: Int, showSnackbar: Boolean = true) { | ||||
|         CoroutineScope(Dispatchers.IO).launch { | ||||
|             repository.markAsRead(i) | ||||
|             repository.markAsRead(item) | ||||
|         } | ||||
|         if (repository.displayedItems == ItemType.UNREAD) { | ||||
|             items.remove(i) | ||||
|             items.remove(item) | ||||
|             notifyItemRemoved(position) | ||||
|             updateItems(items) | ||||
|         } else { | ||||
|             notifyItemChanged(position) | ||||
|         } | ||||
|         if (showSnackbar) { | ||||
|             unmarkSnackbar(position) | ||||
|             unmarkSnackbar(item, position) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun unreadItemAtIndex(position: Int, showSnackbar: Boolean = true) { | ||||
|     private fun unreadItemAtIndex(item: SelfossModel.Item, position: Int, showSnackbar: Boolean = true) { | ||||
|         CoroutineScope(Dispatchers.IO).launch { | ||||
|             repository.unmarkAsRead(items[position]) | ||||
|             repository.unmarkAsRead(item) | ||||
|  | ||||
|         } | ||||
|         notifyItemChanged(position) | ||||
|         if (showSnackbar) { | ||||
|             markSnackbar(position) | ||||
|             markSnackbar(item, position) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -52,11 +52,13 @@ override fun doWork(): Result { | ||||
|  | ||||
|             repository.handleDBActions() | ||||
|  | ||||
|             val apiItems = repository.tryToCacheItemsAndGetNewOnes() | ||||
|             if (appSettingsService.isNotifyNewItemsEnabled()) { | ||||
|                 launch { | ||||
|                     handleNewItemsNotification(repository.tryToCacheItemsAndGetNewOnes(), notificationManager) | ||||
|                     handleNewItemsNotification(apiItems, notificationManager) | ||||
|                 } | ||||
|             } | ||||
|             apiItems.map { it.preloadImages(context) } | ||||
|         } | ||||
|     } | ||||
|     return Result.success() | ||||
| @@ -66,6 +68,7 @@ override fun doWork(): Result { | ||||
|         newItems: List<SelfossModel.Item>?, | ||||
|         notificationManager: NotificationManager | ||||
|     ) { | ||||
|         // TODO: Check if this coroutine is actually required | ||||
|         CoroutineScope(Dispatchers.IO).launch { | ||||
|                 val apiItems = newItems.orEmpty() | ||||
|  | ||||
| @@ -102,7 +105,6 @@ override fun doWork(): Result { | ||||
|                         notificationManager.notify(2, newItemsNotification.build()) | ||||
|                     } | ||||
|                 } | ||||
|                 apiItems.map { it.preloadImages(context) } | ||||
|             Timer("", false).schedule(4000) { | ||||
|                 notificationManager.cancel(1) | ||||
|             } | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import android.graphics.Typeface | ||||
| import android.graphics.drawable.ColorDrawable | ||||
| import android.net.Uri | ||||
| import android.os.Bundle | ||||
| import android.util.TypedValue | ||||
| import android.view.* | ||||
| import android.webkit.WebResourceResponse | ||||
| import android.webkit.WebSettings | ||||
| @@ -56,6 +57,7 @@ import java.net.URL | ||||
| import java.util.* | ||||
| import java.util.concurrent.ExecutionException | ||||
|  | ||||
|  | ||||
| class ArticleFragment : Fragment(), DIAware { | ||||
|     private var fontSize: Int = 16 | ||||
|     private lateinit var item: SelfossModel.Item | ||||
| @@ -333,7 +335,6 @@ class ArticleFragment : Fragment(), DIAware { | ||||
|     } | ||||
|  | ||||
|     private fun htmlToWebview() { | ||||
|         val stringColor = String.format("#%06X", 0xFFFFFF and resources.getColor(R.color.colorAccent)) | ||||
|  | ||||
|         val attrs: IntArray = intArrayOf(android.R.attr.fontFamily) | ||||
|         val a: TypedArray = requireContext().obtainStyledAttributes(resId, attrs) | ||||
| @@ -342,12 +343,11 @@ class ArticleFragment : Fragment(), DIAware { | ||||
|         binding.webcontent.settings.standardFontFamily = a.getString(0) | ||||
|         binding.webcontent.visibility = View.VISIBLE | ||||
|  | ||||
|         // TODO: Set the color strings programmatically | ||||
|         val (stringTextColor, stringBackgroundColor) = if (appSettingsService.isDarkThemeEnabled()) { | ||||
|             Pair("#FFFFFF", "#303030") | ||||
|         } else { | ||||
|             Pair("#212121", "#FAFAFA") | ||||
|         } | ||||
|         val colorOnSurface = TypedValue() | ||||
|         requireContext().theme.resolveAttribute(R.attr.colorOnSurface, colorOnSurface, true) | ||||
|  | ||||
|         val colorSurface = TypedValue() | ||||
|         requireContext().theme.resolveAttribute(R.attr.colorSurface, colorSurface, true) | ||||
|  | ||||
|         binding.webcontent.settings.useWideViewPort = true | ||||
|         binding.webcontent.settings.loadWithOverviewMode = true | ||||
| @@ -436,10 +436,10 @@ class ArticleFragment : Fragment(), DIAware { | ||||
|                 |        max-width: 100%; | ||||
|                 |      } | ||||
|                 |      a { | ||||
|                 |        color: $stringColor !important; | ||||
|                 |        color: ${String.format("#%06X", 0xFFFFFF and resources.getColor(R.color.colorAccent))} !important; | ||||
|                 |      } | ||||
|                 |      *:not(a) { | ||||
|                 |        color: $stringTextColor; | ||||
|                 |        color: ${String.format("#%06X", 0xFFFFFF and colorOnSurface.data)}; | ||||
|                 |      } | ||||
|                 |      * { | ||||
|                 |        font-size: ${fontSize}px; | ||||
| @@ -447,11 +447,11 @@ class ArticleFragment : Fragment(), DIAware { | ||||
|                 |        word-break: break-word; | ||||
|                 |        overflow:hidden; | ||||
|                 |        line-height: 1.5em; | ||||
|                 |        background-color: $stringBackgroundColor; | ||||
|                 |        background-color: ${String.format("#%06X", 0xFFFFFF and colorSurface.data)}; | ||||
|                 |      } | ||||
|                 |      body, html { | ||||
|                 |        background-color: $stringBackgroundColor !important; | ||||
|                 |        border-color: $stringBackgroundColor  !important; | ||||
|                 |        background-color: ${String.format("#%06X", 0xFFFFFF and colorSurface.data)} !important; | ||||
|                 |        border-color: ${String.format("#%06X", 0xFFFFFF and colorSurface.data)}  !important; | ||||
|                 |        padding: 0 !important; | ||||
|                 |        margin: 0 !important; | ||||
|                 |      } | ||||
| @@ -461,7 +461,7 @@ class ArticleFragment : Fragment(), DIAware { | ||||
|                 |      pre, code { | ||||
|                 |        white-space: pre-wrap; | ||||
|                 |        width:100%; | ||||
|                 |        background-color: $stringBackgroundColor; | ||||
|                 |        background-color: ${String.format("#%06X", 0xFFFFFF and colorSurface.data)}; | ||||
|                 |      } | ||||
|                 |   </style> | ||||
|                 |   $fontLinkAndStyle | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import android.text.InputType | ||||
| import android.text.TextWatcher | ||||
| import android.widget.Toast | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.appcompat.app.AppCompatDelegate | ||||
| import androidx.core.widget.addTextChangedListener | ||||
| import androidx.preference.EditTextPreference | ||||
| import androidx.preference.Preference | ||||
| @@ -155,7 +156,11 @@ class SettingsActivity : AppCompatActivity(), | ||||
|     class ThemePreferenceFragment : PreferenceFragmentCompat() { | ||||
|         override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { | ||||
|             setPreferencesFromResource(R.xml.pref_theme, rootKey) | ||||
|             setHasOptionsMenu(true) | ||||
|  | ||||
|             preferenceManager.findPreference<Preference>("currentMode")?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> | ||||
|                 AppCompatDelegate.setDefaultNightMode(newValue.toString().toInt()) // ListPreference Only takes string-arrays ¯\_(ツ)_/¯ | ||||
|                 true | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -16,8 +16,7 @@ | ||||
|     app:layout_constraintTop_toTopOf="parent" | ||||
|     card_view:cardElevation="2dp" | ||||
|     card_view:cardUseCompatPadding="true" | ||||
|     card_view:layout_constraintBottom_toBottomOf="parent" | ||||
|     app:cardBackgroundColor="?cardBackgroundColor"> | ||||
|     card_view:layout_constraintBottom_toBottomOf="parent"> | ||||
|  | ||||
|     <androidx.constraintlayout.widget.ConstraintLayout | ||||
|         android:layout_width="match_parent" | ||||
|   | ||||
| @@ -66,7 +66,7 @@ | ||||
|                 android:layout_marginRight="16dp" | ||||
|                 android:layout_marginTop="24dp" | ||||
|                 android:paddingBottom="48dp" | ||||
|                 android:background="?android:colorBackground" | ||||
|                 android:background="?attr/webviewBackground" | ||||
|                 app:layout_constraintHorizontal_bias="0.0" | ||||
|                 app:layout_constraintLeft_toLeftOf="parent" | ||||
|                 app:layout_constraintRight_toRightOf="parent" | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|     <string name="error_field_required">"Champ requis"</string> | ||||
|     <string name="prompt_url">"Url Selfoss"</string> | ||||
|     <string name="withLoginSwitch">"Avec login ?"</string> | ||||
|     <string name="login_url_problem">"Petit souci. Il manque peut être un / à la fin ?"</string> | ||||
|     <string name="login_url_problem">"Petit souci. Il manque peut-être un / à la fin ?"</string> | ||||
|     <string name="prompt_login">"Utilisateur"</string> | ||||
|     <string name="label_share">"Partager"</string> | ||||
|     <string name="readAll">"Tout lire"</string> | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">La barre sera affichée</string> | ||||
|     <string name="reader_static_bar_off">La barre sera affichée grâce au bouton</string> | ||||
|     <string name="remove_source">Supprimer la source</string> | ||||
|     <string name="pref_theme_title">Thème Clair/Sombre</string> | ||||
|     <string name="mode_dark">Thème sombre</string> | ||||
|     <string name="mode_system">Utiliser les paramètres système</string> | ||||
|     <string name="mode_light">Thème clair</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">A barra inferior mostrarase sempre</string> | ||||
|     <string name="reader_static_bar_off">A barra inferior pode mostrarse a través do botón flotante</string> | ||||
|     <string name="remove_source">Eliminar fonte</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -4,10 +4,10 @@ | ||||
|         <item name="colorPrimaryDark">@color/colorPrimaryDark</item> | ||||
|         <item name="colorAccent">@color/colorAccent</item> | ||||
|         <item name="colorAccentDark">@color/colorAccentDark</item> | ||||
|         <item name="cardBackgroundColor">@color/white</item> | ||||
|         <item name="preferenceTheme">@style/PreferenceStyle</item> | ||||
|         <item name="android:statusBarColor">@color/dark</item> | ||||
|         <item name="bottomBarBackground">@color/dark</item> | ||||
|         <item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item> | ||||
|         <item name="webviewBackground">@color/dark</item> | ||||
|     </style> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -47,7 +47,7 @@ | ||||
|     <string name="switch_unread_count_title">"显示未读数"</string> | ||||
|     <string name="display_all_counts_title">"显示收藏和已读的计数"</string> | ||||
|     <string name="text_wrong_url">"您似乎试图使用无效的 URL。确保它是正确的,如果问题仍然存在,请与我联系 (通过商店的联系链接)。请注意,该应用程序需要您使用 Selfoss。没有它,您无法访问 RSS 源。"</string> | ||||
|     <string name="pref_article_viewer_title">"打开应用程序中的链接"</string> | ||||
|     <string name="pref_article_viewer_title">"在应用内打开链接"</string> | ||||
|     <string name="pref_article_viewer_on">"文章将在应用程序内打开"</string> | ||||
|     <string name="pref_article_viewer_off">"文章将使用默认浏览器打开"</string> | ||||
|     <string name="pref_general_category_links">"链接处理"</string> | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">底部栏将始终显示</string> | ||||
|     <string name="reader_static_bar_off">底部栏可以通过浮动按钮显示</string> | ||||
|     <string name="remove_source">删除源</string> | ||||
|     <string name="pref_theme_title">浅色/深色模式</string> | ||||
|     <string name="mode_dark">深色模式</string> | ||||
|     <string name="mode_system">遵循系统设置</string> | ||||
|     <string name="mode_light">浅色模式</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -128,4 +128,9 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
|     <string name="drawer_error_loading_sources">Error loading sources…</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -4,5 +4,6 @@ | ||||
|         <attr name="colorAccentDark" format="reference|color" /> | ||||
|         <attr name="bottomBarBackground" format="reference|color" /> | ||||
|         <attr name="toolbarPopupTheme" format="reference|color" /> | ||||
|         <attr name="webviewBackground" format="reference|color" /> | ||||
|     </declare-styleable> | ||||
| </resources> | ||||
							
								
								
									
										32
									
								
								androidApp/src/main/res/values/mode_settings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								androidApp/src/main/res/values/mode_settings.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | ||||
|     <string-array name="ModeTitles"> | ||||
|         <item>@string/mode_light</item> | ||||
|         <item>@string/mode_dark</item> | ||||
|         <item>@string/mode_system</item> | ||||
|     </string-array> | ||||
|  | ||||
|     <string-array name="ModeValues"> | ||||
|         <item>1</item> <!--MODE_NIGHT_NO--> | ||||
|         <item>2</item> <!--MODE_NIGHT_YES--> | ||||
|         <item>0</item> <!--MODE_NIGHT_AUTO_TIME--> | ||||
|     </string-array> | ||||
|  | ||||
|     <string-array name="Voice"> | ||||
|         <item>Male</item> | ||||
|         <item>Female</item> | ||||
|     </string-array> | ||||
|  | ||||
|     <string-array name="VoiceAlias"> | ||||
|         <item>"usenglishmale"</item> | ||||
|         <item>"usenglishfemale"</item> | ||||
|         <item>"ukenglishmale"</item> | ||||
|         <item>"ukenglishfemale"</item> | ||||
|         <item>"eurfrenchmale"</item> | ||||
|         <item>"eurfrenchfemale"</item> | ||||
|         <item>"eurspanishmale"</item> | ||||
|         <item>"eurspanishfemale"</item> | ||||
|         <item>"euritalianmale"</item> | ||||
|         <item>"euritalianfemale"</item> | ||||
|     </string-array> | ||||
| </resources> | ||||
| @@ -63,6 +63,7 @@ | ||||
|     <string name="card_height_off">Card height will be fixed</string> | ||||
|     <string name="source_code">Source code</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> | ||||
| @@ -109,7 +110,7 @@ | ||||
|     <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_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> | ||||
| @@ -130,4 +131,8 @@ | ||||
|     <string name="reader_static_bar_on">The bottom bar will always be displayed</string> | ||||
|     <string name="reader_static_bar_off">The bottom bar can be shown through the floating button</string> | ||||
|     <string name="remove_source">Remove source</string> | ||||
|     <string name="pref_theme_title">Light/Dark mode</string> | ||||
|     <string name="mode_dark">Dark mode</string> | ||||
|     <string name="mode_system">Follow the system setting</string> | ||||
|     <string name="mode_light">Light mode</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -9,11 +9,11 @@ | ||||
|         <item name="colorPrimaryDark">@color/colorPrimaryDark</item> | ||||
|         <item name="colorAccent">@color/colorAccent</item> | ||||
|         <item name="colorAccentDark">@color/colorAccentDark</item> | ||||
|         <item name="cardBackgroundColor">@color/white</item> | ||||
|         <item name="preferenceTheme">@style/PreferenceStyle</item> | ||||
|         <item name="android:statusBarColor">?attr/colorPrimary</item> | ||||
|         <item name="bottomBarBackground">@color/white</item> | ||||
|         <item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item> | ||||
|         <item name="webviewBackground">@color/white</item> | ||||
|     </style> | ||||
|  | ||||
|     <!-- Preference Theme --> | ||||
|   | ||||
| @@ -1,11 +1,13 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto"> | ||||
|     <!-- TODO translate this file --> | ||||
|  | ||||
|     <SwitchPreference | ||||
|         android:defaultValue="false" | ||||
|         android:key="dark_theme" | ||||
|     <ListPreference | ||||
|         android:defaultValue="0" | ||||
|         android:entries="@array/ModeTitles" | ||||
|         android:entryValues="@array/ModeValues" | ||||
|         android:key="currentMode" | ||||
|         app:iconSpaceReserved="false" | ||||
|         android:title="Dark theme" /> | ||||
|         android:title="@string/pref_theme_title" | ||||
|         app:useSimpleSummaryProvider="false" /> | ||||
| </PreferenceScreen> | ||||
| @@ -56,6 +56,8 @@ kotlin { | ||||
|             dependencies { | ||||
|                 implementation(kotlin("test-common")) | ||||
|                 implementation(kotlin("test-annotations-common")) | ||||
|                 implementation("io.mockk:mockk:1.12.0") | ||||
|                 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") | ||||
|             } | ||||
|         } | ||||
|         val androidMain by getting { | ||||
|   | ||||
| @@ -138,7 +138,11 @@ class SelfossModel { | ||||
|     object BooleanSerializer : KSerializer<Boolean> { | ||||
|         override fun deserialize(decoder: Decoder): Boolean { | ||||
|             val json = ((decoder as JsonDecoder).decodeJsonElement()).jsonPrimitive | ||||
|             return json.booleanOrNull ?: json.int == 1 | ||||
|             return if (json.booleanOrNull != null) { | ||||
|                 json.boolean | ||||
|             } else { | ||||
|                 json.int == 1 | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         override val descriptor: SerialDescriptor | ||||
|   | ||||
| @@ -11,6 +11,7 @@ import io.github.aakira.napier.Napier | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.launch | ||||
| import kotlinx.coroutines.runBlocking | ||||
|  | ||||
| class Repository(private val api: SelfossApi, private val appSettingsService: AppSettingsService, connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) { | ||||
|  | ||||
| @@ -36,9 +37,13 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|     var badgeStarred = 0 | ||||
|     set(value) {field = if (value < 0) { 0 } else { value } } | ||||
|  | ||||
|     private var fetchedSources = false | ||||
|     private var fetchedTags = false | ||||
|  | ||||
|     init { | ||||
|         // TODO: Dispatchers.IO not available in KMM, an alternative solution should be found | ||||
|         CoroutineScope(Dispatchers.Main).launch { | ||||
|         connectivityStatus.start() | ||||
|         runBlocking { | ||||
|             updateApiVersion() | ||||
|             dateUtils = DateUtils(appSettingsService) | ||||
|             reloadBadges() | ||||
| @@ -61,12 +66,19 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|         } else { | ||||
|             if (appSettingsService.isItemCachingEnabled()) { | ||||
|                 fromDB = true | ||||
|                 var dbItems = getDBItems().filter { | ||||
|                     displayedItems == ItemType.ALL || | ||||
|                             (it.unread && displayedItems == ItemType.UNREAD) || | ||||
|                             (it.starred && displayedItems == ItemType.STARRED) | ||||
|                 } | ||||
|                 if (tagFilter != null) { | ||||
|                     dbItems = dbItems.filter { it.tags.split(',').contains(tagFilter!!.tag) } | ||||
|                 } | ||||
|                 if (sourceFilter != null) { | ||||
|                     dbItems = dbItems.filter { it.sourcetitle == sourceFilter!!.title } | ||||
|                 } | ||||
|                 fetchedItems = SelfossModel.StatusAndData.succes( | ||||
|                     getDBItems().filter { | ||||
|                         displayedItems == ItemType.ALL || | ||||
|                                 (it.unread && displayedItems == ItemType.UNREAD) || | ||||
|                                 (it.starred && displayedItems == ItemType.STARRED) | ||||
|                     }.map { it.toView() } | ||||
|                     dbItems.map { it.toView() } | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
| @@ -105,9 +117,9 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|             val items = api.getItems( | ||||
|                 itemType.type, | ||||
|                 0, | ||||
|                 tagFilter?.tag, | ||||
|                 sourceFilter?.id?.toLong(), | ||||
|                 searchFilter, | ||||
|                 null, | ||||
|                 null, | ||||
|                 null, | ||||
|                 null, | ||||
|                 200 | ||||
|             ) | ||||
| @@ -131,32 +143,40 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|                 badgeStarred = response.data.starred | ||||
|                 success = true | ||||
|             } | ||||
|         } else { | ||||
|         } else if (appSettingsService.isItemCachingEnabled()) { | ||||
|             // TODO: do this differently, because it's not efficient | ||||
|             val dbItems = getDBItems() | ||||
|             badgeUnread = dbItems.filter { item -> item.unread }.size | ||||
|             badgeStarred = dbItems.filter { item -> item.starred }.size | ||||
|             badgeAll = items.size | ||||
|             badgeAll = dbItems.size | ||||
|             success = true | ||||
|         } | ||||
|         return success | ||||
|     } | ||||
|  | ||||
|     suspend fun getTags(): List<SelfossModel.Tag>? { | ||||
|         return if (isNetworkAvailable()) { | ||||
|     suspend fun getTags(): List<SelfossModel.Tag> { | ||||
|         val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled() | ||||
|         return if (isNetworkAvailable() && !fetchedTags) { | ||||
|             val apiTags = api.tags() | ||||
|             if (apiTags.success && apiTags.data != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) { | ||||
|             if (apiTags.success && apiTags.data != null && isDatabaseEnabled) { | ||||
|                 resetDBTagsWithData(apiTags.data) | ||||
|                 if (!appSettingsService.isUpdateSourcesEnabled()) { | ||||
|                     fetchedTags = true | ||||
|                 } | ||||
|             } | ||||
|             apiTags.data | ||||
|         } else { | ||||
|             apiTags.data ?: emptyList() | ||||
|         } else if (isDatabaseEnabled) { | ||||
|             getDBTags().map { it.toView() } | ||||
|         } else { | ||||
|             emptyList() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     suspend fun getSpouts(): Map<String, SelfossModel.Spout>? { | ||||
|     // TODO: Add tests | ||||
|     suspend fun getSpouts(): Map<String, SelfossModel.Spout> { | ||||
|         return if (isNetworkAvailable()) { | ||||
|             val spouts = api.spouts() | ||||
|             return if (spouts.success && spouts.data != null) { | ||||
|             if (spouts.success && spouts.data != null) { | ||||
|                 spouts.data | ||||
|             } else { | ||||
|                 emptyMap() // TODO: do something here | ||||
| @@ -166,18 +186,25 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     suspend fun getSources(): ArrayList<SelfossModel.Source>? { | ||||
|         return if (isNetworkAvailable()) { | ||||
|     suspend fun getSources(): ArrayList<SelfossModel.Source> { | ||||
|         val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled() | ||||
|         return if (isNetworkAvailable() && !fetchedSources) { | ||||
|             val apiSources = api.sources() | ||||
|             if (apiSources.success && apiSources.data != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) { | ||||
|             if (apiSources.success && apiSources.data != null && isDatabaseEnabled) { | ||||
|                 resetDBSourcesWithData(apiSources.data) | ||||
|                 if (!appSettingsService.isUpdateSourcesEnabled()) { | ||||
|                     fetchedSources = true | ||||
|                 } | ||||
|             } | ||||
|             apiSources.data | ||||
|         } else { | ||||
|             apiSources.data ?: ArrayList() | ||||
|         } else if (isDatabaseEnabled) { | ||||
|             ArrayList(getDBSources().map { it.toView() }) | ||||
|         } else { | ||||
|             ArrayList() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // TODO: Add tests | ||||
|     suspend fun markAsRead(item: SelfossModel.Item): Boolean { | ||||
|         val success = markAsReadById(item.id) | ||||
|  | ||||
| @@ -189,14 +216,14 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|  | ||||
|     private suspend fun markAsReadById(id: Int): Boolean { | ||||
|         return if (isNetworkAvailable()) { | ||||
|             api.markAsRead(id.toString())?.isSuccess | ||||
|             api.markAsRead(id.toString()).isSuccess | ||||
|         } else { | ||||
|             insertDBAction(id.toString(), read = true) | ||||
|             true | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     // TODO: Add tests | ||||
|     suspend fun unmarkAsRead(item: SelfossModel.Item): Boolean { | ||||
|         val success = unmarkAsReadById(item.id) | ||||
|  | ||||
| @@ -208,13 +235,14 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|  | ||||
|     private suspend fun unmarkAsReadById(id: Int): Boolean { | ||||
|         return if (isNetworkAvailable()) { | ||||
|             api.unmarkAsRead(id.toString())?.isSuccess | ||||
|             api.unmarkAsRead(id.toString()).isSuccess | ||||
|         } else { | ||||
|             insertDBAction(id.toString(), unread = true) | ||||
|             true | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // TODO: Add tests | ||||
|     suspend fun starr(item: SelfossModel.Item): Boolean { | ||||
|         val success = starrById(item.id) | ||||
|  | ||||
| @@ -226,13 +254,14 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|  | ||||
|     private suspend fun starrById(id: Int): Boolean { | ||||
|         return if (isNetworkAvailable()) { | ||||
|             api.starr(id.toString())?.isSuccess | ||||
|             api.starr(id.toString()).isSuccess | ||||
|         } else { | ||||
|             insertDBAction(id.toString(), starred = true) | ||||
|             true | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // TODO: Add tests | ||||
|     suspend fun unstarr(item: SelfossModel.Item): Boolean { | ||||
|         val success = unstarrById(item.id) | ||||
|  | ||||
| @@ -244,17 +273,18 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|  | ||||
|     private suspend fun unstarrById(id: Int): Boolean { | ||||
|         return if (isNetworkAvailable()) { | ||||
|             api.unstarr(id.toString())?.isSuccess | ||||
|             api.unstarr(id.toString()).isSuccess | ||||
|         } else { | ||||
|             insertDBAction(id.toString(), starred = true) | ||||
|             true | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // TODO: Add tests | ||||
|     suspend fun markAllAsRead(items: ArrayList<SelfossModel.Item>): Boolean { | ||||
|         var success = false | ||||
|  | ||||
|         if (isNetworkAvailable() && api.markAllAsRead(items.map { it.id.toString() })?.isSuccess) { | ||||
|         if (isNetworkAvailable() && api.markAllAsRead(items.map { it.id.toString() }).isSuccess) { | ||||
|             success = true | ||||
|             for (item in items) { | ||||
|                 markAsReadLocally(item) | ||||
| @@ -323,7 +353,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|                 tags, | ||||
|                 filter, | ||||
|                 appSettingsService.getApiVersion() | ||||
|             )?.isSuccess == true | ||||
|             ).isSuccess == true | ||||
|         } | ||||
|  | ||||
|         return response | ||||
| @@ -333,9 +363,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|         var success = false | ||||
|         if (isNetworkAvailable()) { | ||||
|             val response = api.deleteSource(id) | ||||
|             if (response != null) { | ||||
|                 success = response.isSuccess | ||||
|             } | ||||
|             success = response.isSuccess | ||||
|         } | ||||
|  | ||||
|         return success | ||||
| @@ -343,7 +371,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|  | ||||
|     suspend fun updateRemote(): Boolean { | ||||
|         return if (isNetworkAvailable()) { | ||||
|             api.update()?.equals("finished") | ||||
|             api.update().data.equals("finished") | ||||
|         } else { | ||||
|             false | ||||
|         } | ||||
| @@ -354,7 +382,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|         if (isNetworkAvailable()) { | ||||
|             try { | ||||
|                 val response = api.login() | ||||
|                 result = response?.isSuccess == true | ||||
|                 result = response.isSuccess == true | ||||
|                 if (result) { | ||||
|                     updateApiVersion() | ||||
|                 } | ||||
| @@ -371,7 +399,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|         api.refreshLoginInformation() | ||||
|     } | ||||
|  | ||||
|     suspend fun updateApiVersion() { | ||||
|     private suspend fun updateApiVersion() { | ||||
|         val apiMajorVersion = appSettingsService.getApiVersion() | ||||
|  | ||||
|         if (isNetworkAvailable()) { | ||||
| @@ -390,9 +418,9 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|     private fun deleteDBAction(action: ACTION) = | ||||
|         db.actionsQueries.deleteAction(action.id) | ||||
|  | ||||
|     fun getDBTags(): List<TAG> = db.tagsQueries.tags().executeAsList() | ||||
|     private fun getDBTags(): List<TAG> = db.tagsQueries.tags().executeAsList() | ||||
|  | ||||
|     fun getDBSources(): List<SOURCE> = db.sourcesQueries.sources().executeAsList() | ||||
|     private fun getDBSources(): List<SOURCE> = db.sourcesQueries.sources().executeAsList() | ||||
|  | ||||
|     private fun resetDBTagsWithData(tagEntities: List<SelfossModel.Tag>) { | ||||
|         db.tagsQueries.deleteAllTags() | ||||
| @@ -430,8 +458,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|     private fun updateDBItem(item: SelfossModel.Item) = | ||||
|         db.itemsQueries.updateItem(item.datetime, item.title.getHtmlDecoded(), item.content, item.unread, item.starred, item.thumbnail, item.icon, item.link, item.sourcetitle, item.tags.joinToString(","), item.id.toString()) | ||||
|  | ||||
|  | ||||
|     suspend fun tryToCacheItemsAndGetNewOnes(): List<SelfossModel.Item>? { | ||||
|     suspend fun tryToCacheItemsAndGetNewOnes(): List<SelfossModel.Item> { | ||||
|         try { | ||||
|             val newItems = getMaxItemsForBackground(ItemType.UNREAD) | ||||
|             val allItems = getMaxItemsForBackground(ItemType.ALL) | ||||
| @@ -444,6 +471,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap | ||||
|         return emptyList() | ||||
|     } | ||||
|  | ||||
|     // TODO: Add tests | ||||
|     suspend fun handleDBActions() { | ||||
|  | ||||
|         val actions: List<ACTION> = getDBActions() | ||||
|   | ||||
| @@ -34,7 +34,6 @@ class AppSettingsService { | ||||
|  | ||||
|     private var _fontSize: Int? = null | ||||
|     private var _staticBar: Boolean? = null | ||||
|     private var _darkTheme: Boolean? = null | ||||
|     private var _font: String = "" | ||||
|  | ||||
|  | ||||
| @@ -308,17 +307,6 @@ class AppSettingsService { | ||||
|         return _staticBar == true | ||||
|     } | ||||
|  | ||||
|     private fun refreshDarkThemeEnabled() { | ||||
|         _darkTheme = settings.getBoolean("dark_theme", false) | ||||
|     } | ||||
|  | ||||
|     fun isDarkThemeEnabled(): Boolean { | ||||
|         if (_darkTheme != null) { | ||||
|             refreshDarkThemeEnabled() | ||||
|         } | ||||
|         return _darkTheme == true | ||||
|     } | ||||
|  | ||||
|     private fun refreshFont() { | ||||
|         _font = settings.getString("reader_font", "") | ||||
|     } | ||||
| @@ -358,7 +346,6 @@ class AppSettingsService { | ||||
|         refreshFontSize() | ||||
|         refreshFont() | ||||
|         refreshStaticBarEnabled() | ||||
|         refreshDarkThemeEnabled() | ||||
|     } | ||||
|  | ||||
|     fun refreshLoginInformation( | ||||
|   | ||||
| @@ -65,6 +65,6 @@ fun SelfossModel.Item.toEntity(): ITEM = | ||||
|         this.thumbnail, | ||||
|         this.icon, | ||||
|         this.link, | ||||
|         this.title.getHtmlDecoded(), | ||||
|         this.sourcetitle.getHtmlDecoded(), | ||||
|         this.tags.joinToString(",") | ||||
|     ) | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user