Closes #44
continuous-integration/drone/push Build was killed
continuous-integration/drone/pr Build is passing

This commit is contained in:
aminecmi
2022-08-28 10:30:03 +02:00
parent 94f1ec943c
commit fc4c48dd12
22 changed files with 218 additions and 400 deletions
@@ -49,14 +49,12 @@ import com.mikepenz.materialdrawer.holder.ColorHolder
import com.mikepenz.materialdrawer.holder.StringHolder
import com.mikepenz.materialdrawer.model.DividerDrawerItem
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.*
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
import com.mikepenz.materialdrawer.util.DrawerImageLoader
import com.mikepenz.materialdrawer.util.addStickyFooterItem
import com.mikepenz.materialdrawer.util.updateBadge
import com.mikepenz.materialdrawer.widget.AccountHeaderView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -137,7 +135,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
customTabActivityHelper = CustomTabActivityHelper()
handleBottomBar()
handleDrawer()
initDrawer()
handleSwipeRefreshLayout()
@@ -147,7 +145,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
CoroutineScope(Dispatchers.Main).launch {
repository.tryToCacheItemsAndGetNewOnes()
}
}
private fun handleSwipeRefreshLayout() {
@@ -323,17 +320,17 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
scoop.update(Toppings.PRIMARY_DARK.value, appColors.colorPrimaryDark)
}
private fun handleDrawer() {
private fun initDrawer() {
DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
Glide.with(this@HomeActivity)
.asBitmap()
.load(uri)
.apply(RequestOptions()
.placeholder(R.mipmap.ic_launcher)
.fallback(R.mipmap.ic_launcher)
.fitCenter())
.into(imageView)
.asBitmap()
.load(uri)
.apply(RequestOptions()
.placeholder(R.mipmap.ic_launcher)
.fallback(R.mipmap.ic_launcher)
.fitCenter())
.into(imageView)
}
override fun cancel(imageView: ImageView) {
@@ -362,285 +359,31 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
binding.drawerContainer.addDrawerListener(drawerListener)
binding.mainDrawer.addStickyFooterItem(
PrimaryDrawerItem().apply {
nameRes = R.string.drawer_report_bug
iconRes = R.drawable.ic_bug_report_black_24dp
isIconTinted = true
onDrawerItemClickListener = { _, _, _ ->
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(AppSettingsService.trackerUrl))
startActivity(browserIntent)
false
}
})
binding.mainDrawer.addStickyFooterItem(
PrimaryDrawerItem().apply {
nameRes = R.string.title_activity_settings
iconRes = R.drawable.ic_settings_black_24dp
isIconTinted = true
onDrawerItemClickListener = { _, _, _ ->
startActivityForResult(Intent(this@HomeActivity, SettingsActivity::class.java), SETTINGS_ACTIVITY)
false
}
})
if (appSettingsService.isDisplayAccountHeaderEnabled()) {
AccountHeaderView(this).apply {
attachToSliderView(binding.mainDrawer)
addProfiles(
ProfileDrawerItem().apply {
nameText = appSettingsService.getBaseUrl()
setBackgroundResource(R.drawable.bg)
iconRes = R.mipmap.ic_launcher
selectionListEnabledForSingleProfile = false
}
)
}
// Sticky items
addStickyPrimaryItem(R.string.drawer_report_bug, R.drawable.ic_bug_report_black_24dp) { _, _, _ ->
val browserIntent =
Intent(Intent.ACTION_VIEW, Uri.parse(AppSettingsService.trackerUrl))
startActivity(browserIntent)
false
}
addStickyPrimaryItem(R.string.title_activity_settings, R.drawable.ic_settings_black_24dp) { _, _, _ ->
startActivityForResult(Intent(this@HomeActivity, SettingsActivity::class.java), SETTINGS_ACTIVITY)
false
}
}
// TODO: refactor this.
// TODO: use updateSources
private fun addStickyPrimaryItem(name: Int, icon: Int, clickListener: ((v: View?, item: IDrawerItem<*>, position: Int) -> Boolean)?) {
binding.mainDrawer.addStickyFooterItem(
PrimaryDrawerItem().apply {
nameRes = name
iconRes = icon
isIconTinted = true
onDrawerItemClickListener = clickListener
})
}
private fun handleDrawerItems() {
tagsBadge = emptyMap()
fun handleDrawerData(maybeDrawerData: DrawerData?, loadedFromCache: Boolean = false) {
fun createDrawerItem(
it: SelfossModel.Tag
) {
val gd = GradientDrawable()
val gdColor = try {
Color.parseColor(it.color)
} catch (e: IllegalArgumentException) {
appColors.colorPrimary
}
gd.setColor(gdColor)
gd.shape = GradientDrawable.RECTANGLE
gd.setSize(30, 30)
gd.cornerRadius = 30F
val drawerItem = PrimaryDrawerItem()
.apply {
nameText = it.tag.getHtmlDecoded()
identifier = it.tag.longHash()
iconDrawable = gd
badgeStyle = BadgeStyle().apply {
textColor = ColorHolder.fromColor(Color.WHITE)
color = ColorHolder.fromColor(appColors.colorAccent)
}
onDrawerItemClickListener = { _, _, _ ->
repository.tagFilter = it
repository.sourceFilter = null
getElementsAccordingToTab()
fetchOnEmptyList()
false
}
}
if (it.unread > 0) {
drawerItem.badgeText = it.unread.toString()
}
binding.mainDrawer.itemAdapter.add(drawerItem)
}
fun handleTags(maybeTags: List<SelfossModel.Tag>?) {
if (maybeTags == null) {
if (loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem()
.apply { nameRes = R.string.drawer_error_loading_tags; isSelectable = false }
)
}
} else {
val filteredTags = maybeTags
.filterNot { appSettingsService.getHiddenTags().contains(it.tag) }
.sortedBy { it.unread == 0 }
tagsBadge = filteredTags.map {
createDrawerItem(it)
(it.tag.longHash() to it.unread)
}.toMap()
}
}
fun handleHiddenTags(maybeTags: List<SelfossModel.Tag>?) {
if (maybeTags == null) {
if (loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_error_loading_tags
isSelectable = false
}
)
}
} else {
val filteredHiddenTags: List<SelfossModel.Tag> =
maybeTags.filter { appSettingsService.getHiddenTags().contains(it.tag) }
tagsBadge = filteredHiddenTags.map {
createDrawerItem(it)
(it.tag.longHash() to it.unread)
}.toMap()
}
}
fun handleSources(maybeSources: List<SelfossModel.Source>?) {
if (maybeSources == null) {
if (loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_error_loading_sources
isSelectable = false
}
)
}
} else {
for (source in maybeSources) {
val item = PrimaryDrawerItem().apply {
nameText = source.title.getHtmlDecoded()
identifier = source.id.toLong()
iconUrl = source.getIcon(repository.baseUrl)
onDrawerItemClickListener = { _,_,_ ->
repository.sourceFilter = source
repository.tagFilter = null
getElementsAccordingToTab()
fetchOnEmptyList()
false
}
}
binding.mainDrawer.itemAdapter.add(item)
}
}
}
binding.mainDrawer.itemAdapter.clear()
if (maybeDrawerData != null) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_item_filters
isSelectable = false
identifier = DRAWER_ID_FILTERS
badgeRes = R.string.drawer_action_clear
onDrawerItemClickListener = { _,_,_ ->
repository.sourceFilter = null
repository.tagFilter = null
binding.mainDrawer.setSelectionAtPosition(-1)
getElementsAccordingToTab()
fetchOnEmptyList()
false
}
}
)
if (appSettingsService.getHiddenTags().isNotEmpty()) {
binding.mainDrawer.itemAdapter.add(
DividerDrawerItem(),
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_item_hidden_tags
identifier = DRAWER_ID_HIDDEN_TAGS
isSelectable = false
}
)
handleHiddenTags(maybeDrawerData.tags)
}
binding.mainDrawer.itemAdapter.add(
DividerDrawerItem(),
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_item_tags
identifier = DRAWER_ID_TAGS
isSelectable = false
}
)
handleTags(maybeDrawerData.tags)
binding.mainDrawer.itemAdapter.add(
DividerDrawerItem(),
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_item_sources
identifier = DRAWER_ID_SOURCES
isSelectable = false
badgeRes = R.string.drawer_action_edit
onDrawerItemClickListener = { v,_,_ ->
startActivity(Intent(v!!.context, SourcesActivity::class.java))
false
}
}
)
handleSources(maybeDrawerData.sources)
binding.mainDrawer.itemAdapter.add(
DividerDrawerItem(),
PrimaryDrawerItem().apply {
nameRes = R.string.action_about
isSelectable = false
iconRes = R.drawable.ic_info_outline_white_24dp
isIconTinted = true
onDrawerItemClickListener = { _,_,_ ->
LibsBuilder()
.withAboutIconShown(true)
.withAboutVersionShown(true)
.start(this@HomeActivity)
false
}
}
)
if (!loadedFromCache) {
if (maybeDrawerData.tags != null) {
thread {
repository.resetDBTagsWithData(maybeDrawerData.tags)
}
}
if (maybeDrawerData.sources != null) {
thread {
repository.resetDBSourcesWithData(maybeDrawerData.sources)
}
}
}
} else {
if (!loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
PrimaryDrawerItem().apply {
nameRes = R.string.no_tags_loaded
identifier = DRAWER_ID_TAGS
isSelectable = false
},
PrimaryDrawerItem().apply {
nameRes = R.string.no_sources_loaded
identifier = DRAWER_ID_SOURCES
isSelectable = false
}
)
}
}
}
fun drawerApiCalls(maybeDrawerData: DrawerData?) {
var tags: List<SelfossModel.Tag>? = null
var sources: List<SelfossModel.Source>?
fun sourcesApiCall() {
CoroutineScope(Dispatchers.Main).launch {
val response = repository.getSources()
if (response != null) {
sources = response
val apiDrawerData = DrawerData(tags, sources)
if ((maybeDrawerData != null && maybeDrawerData != apiDrawerData) || maybeDrawerData == null) {
handleDrawerData(apiDrawerData)
}
} else {
val apiDrawerData = DrawerData(tags, null)
if ((maybeDrawerData != null && maybeDrawerData != apiDrawerData) || maybeDrawerData == null) {
handleDrawerData(apiDrawerData)
}
}
}
}
CoroutineScope(Dispatchers.IO).launch {
tags = repository.getTags()
sourcesApiCall()
}
}
binding.mainDrawer.itemAdapter.add(
PrimaryDrawerItem().apply {
nameRes = R.string.drawer_loading
@@ -648,16 +391,189 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
}
)
thread {
CoroutineScope(Dispatchers.IO).launch {
val drawerData = DrawerData(repository.getDBTags().map { it.toView() },
repository.getDBSources().map { it.toView() })
runOnUiThread {
handleDrawerData(drawerData, loadedFromCache = true)
drawerApiCalls(drawerData)
// Only refresh if there is no data in the DB, or if the `UpdateSources` setting is enabled
if (drawerData.sources?.isEmpty() == true || appSettingsService.isUpdateSourcesEnabled()) {
drawerApiCalls(drawerData)
} else {
handleDrawerData(drawerData, loadedFromCache = true)
}
}
}
}
private fun drawerApiCalls(drawerData: DrawerData) {
CoroutineScope(Dispatchers.Main).launch {
val apiDrawerData = DrawerData(repository.getTags(), repository.getSources())
handleDrawerData(if (drawerData != apiDrawerData) apiDrawerData else drawerData)
}
}
private fun handleDrawerData(drawerData: DrawerData, loadedFromCache: Boolean = false) {
binding.mainDrawer.itemAdapter.clear()
// Filters title with clear action
secondaryItem(withDivider = false, R.string.drawer_item_filters, DRAWER_ID_FILTERS, R.string.drawer_action_clear) { _,_,_ ->
repository.sourceFilter = null
repository.tagFilter = null
binding.mainDrawer.setSelectionAtPosition(-1)
getElementsAccordingToTab()
fetchOnEmptyList()
false
}
// Hidden tags
if (drawerData.tags != null && drawerData.tags.isNotEmpty() && appSettingsService.getHiddenTags().isNotEmpty()) {
secondaryItem(
withDivider = true,
R.string.drawer_item_hidden_tags,
DRAWER_ID_HIDDEN_TAGS
)
handleHiddenTags(drawerData.tags)
}
// Tags
secondaryItem(withDivider = true, R.string.drawer_item_tags, DRAWER_ID_TAGS)
if (drawerData.tags == null && !loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem()
.apply { nameRes = R.string.drawer_error_loading_tags; isSelectable = false }
)
} else {
handleTags(drawerData.tags!!)
}
// Sources
secondaryItem(withDivider = true, R.string.drawer_item_sources, DRAWER_ID_SOURCES, R.string.drawer_action_edit) { v, _, _ ->
startActivity(Intent(v!!.context, SourcesActivity::class.java))
false
}
if (drawerData.sources == null && !loadedFromCache) {
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem().apply {
nameRes = R.string.drawer_error_loading_tags
isSelectable = false
}
)
} else {
handleSources(drawerData.sources!!)
}
// About action
binding.mainDrawer.itemAdapter.add(
DividerDrawerItem(),
PrimaryDrawerItem().apply {
nameRes = R.string.action_about
isSelectable = false
iconRes = R.drawable.ic_info_outline_white_24dp
isIconTinted = true
onDrawerItemClickListener = { _,_,_ ->
LibsBuilder()
.withAboutIconShown(true)
.withAboutVersionShown(true)
.start(this@HomeActivity)
false
}
}
)
}
private fun secondaryItem(withDivider: Boolean, name: Int, id: Long, badgeId: Int? = null, clickListener: ((v: View?, item: IDrawerItem<*>, position: Int) -> Boolean)? = null) {
if (withDivider) {
binding.mainDrawer.itemAdapter.add(DividerDrawerItem())
}
binding.mainDrawer.itemAdapter.add(
SecondaryDrawerItem().apply {
nameRes = name
identifier = id
isSelectable = false
if (badgeId != null) {
badgeRes = badgeId
}
onDrawerItemClickListener = clickListener
}
)
}
private fun createDrawerItem(it: SelfossModel.Tag) {
val gd = GradientDrawable()
val gdColor = try {
Color.parseColor(it.color)
} catch (e: IllegalArgumentException) {
appColors.colorPrimary
}
gd.setColor(gdColor)
gd.shape = GradientDrawable.RECTANGLE
gd.setSize(30, 30)
gd.cornerRadius = 30F
val drawerItem = PrimaryDrawerItem()
.apply {
nameText = it.tag.getHtmlDecoded()
identifier = it.tag.longHash()
iconDrawable = gd
badgeStyle = BadgeStyle().apply {
textColor = ColorHolder.fromColor(Color.WHITE)
color = ColorHolder.fromColor(appColors.colorAccent)
}
onDrawerItemClickListener = { _, _, _ ->
repository.tagFilter = it
repository.sourceFilter = null
getElementsAccordingToTab()
fetchOnEmptyList()
false
}
}
if (it.unread > 0) {
drawerItem.badgeText = it.unread.toString()
}
binding.mainDrawer.itemAdapter.add(drawerItem)
}
private fun handleTags(tags: List<SelfossModel.Tag>) {
val filteredTags = tags
.filterNot { appSettingsService.getHiddenTags().contains(it.tag) }
.sortedBy { it.tag }
createTagItems(filteredTags)
}
private fun handleHiddenTags(tags: List<SelfossModel.Tag>) {
val filteredHiddenTags: List<SelfossModel.Tag> =
tags.filter { appSettingsService.getHiddenTags().contains(it.tag) }
createTagItems(filteredHiddenTags)
}
private fun createTagItems(tags: List<SelfossModel.Tag>) {
tagsBadge = tags.associate {
createDrawerItem(it)
(it.tag.longHash() to it.unread)
}
}
private fun handleSources(sources: List<SelfossModel.Source>) {
for (source in sources) {
val item = PrimaryDrawerItem().apply {
nameText = source.title.getHtmlDecoded()
identifier = source.id.toLong()
iconUrl = source.getIcon(repository.baseUrl)
onDrawerItemClickListener = { _,_,_ ->
repository.sourceFilter = source
repository.tagFilter = null
getElementsAccordingToTab()
fetchOnEmptyList()
false
}
}
binding.mainDrawer.itemAdapter.add(item)
}
}
private fun reloadLayoutManager() {
val currentManager = binding.recyclerView.layoutManager
val layoutManager: RecyclerView.LayoutManager
Internal Server Error - Amine's git
500 Internal Server Error

Gitea Version: 1.28.0+dev-211-ga30d865b78