Skip to content

Commit

Permalink
Restore xml view for overlay service
Browse files Browse the repository at this point in the history
Signed-off-by: Saul Henriquez <[email protected]>
  • Loading branch information
saulhdev committed Jan 27, 2024
1 parent 03b7cbd commit 44ddea6
Show file tree
Hide file tree
Showing 18 changed files with 1,073 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ package com.google.android.apps.gsa.nowoverlayservice

import android.app.Service
import android.content.res.Configuration

import com.google.android.libraries.gsa.d.a.OverlayController
import com.google.android.libraries.gsa.d.a.OverlaysController
import com.google.android.libraries.gsa.d.a.v
import com.saulhdev.feeder.overlay.ComposeOverlayView
import com.saulhdev.feeder.overlay.OverlayView

class ConfigurationOverlayController(private val service: Service) : OverlaysController(service) {
override fun Hx() = 24
Expand All @@ -15,7 +14,7 @@ class ConfigurationOverlayController(private val service: Service) : OverlaysCon
configuration: Configuration?,
i: Int,
i2: Int
): OverlayController = ComposeOverlayView(
): OverlayController = OverlayView(
if (configuration != null) service.createConfigurationContext(configuration) else service
)

Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/com/saulhdev/feeder/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ class MainActivity : ComponentActivity(), SavedStateRegistryOwner {
WindowCompat.setDecorFitsSystemWindows(window, false)
prefs = FeedPreferences.getInstance(this)
setContent {
navController = rememberNavController()
AppTheme(
darkTheme = isDarkTheme
) {
TransparentSystemBars()
navController = rememberNavController()
NavigationManager(navController = navController)
}
}
Expand All @@ -76,6 +76,7 @@ class MainActivity : ComponentActivity(), SavedStateRegistryOwner {
configurePeriodicSync(prefs)
observePrefs()
NFApplication.mainActivity = this

}

@Composable
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/saulhdev/feeder/NFApplication.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.saulhdev.feeder

import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.widget.Toast
import androidx.lifecycle.SavedStateHandle
Expand Down Expand Up @@ -67,6 +68,7 @@ class NFApplication : MultiDexApplication() {
}
}
single { applicationCoroutineScope }
single<Application> { this@NFApplication }
}

override fun onCreate() {
Expand Down
67 changes: 67 additions & 0 deletions app/src/main/java/com/saulhdev/feeder/feed/FeedAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* This file is part of Neo Feed
* Copyright (c) 2024 NeoApplications Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.saulhdev.feeder.feed

import android.util.SparseIntArray
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.saulhdev.feeder.R
import com.saulhdev.feeder.feed.binders.StoryCardBinder
import com.saulhdev.feeder.sdk.FeedItem

class FeedAdapter : RecyclerView.Adapter<FeedAdapter.FeedViewHolder>() {
private var list = listOf<FeedItem>()
private lateinit var layoutInflater: LayoutInflater
private var theme: SparseIntArray? = null

fun replace(new: List<FeedItem>) {
list = new
notifyDataSetChanged()
}

fun setTheme(theme: SparseIntArray) {
this.theme = theme
notifyDataSetChanged()
}

override fun getItemCount(): Int {
return list.size
}

override fun getItemViewType(position: Int): Int {
return (list[position].type.ordinal)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FeedViewHolder {
if (!::layoutInflater.isInitialized) layoutInflater = LayoutInflater.from(parent.context)

val layoutResource = R.layout.feed_card_story_large

return FeedViewHolder(viewType, layoutInflater.inflate(layoutResource, parent, false))
}

override fun onBindViewHolder(holder: FeedViewHolder, position: Int) {
val item = list[position]
StoryCardBinder.bind(theme, item, holder.itemView)
}

inner class FeedViewHolder(val type: Int, itemView: View) : RecyclerView.ViewHolder(itemView)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.saulhdev.feeder.feed.binders

import android.util.SparseIntArray
import android.view.View
import com.saulhdev.feeder.sdk.FeedItem

interface FeedBinder {
fun bind(theme: SparseIntArray?, item: FeedItem, view: View)
}
122 changes: 122 additions & 0 deletions app/src/main/java/com/saulhdev/feeder/feed/binders/StoryCardBinder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.saulhdev.feeder.feed.binders

import android.content.Intent
import android.text.Html
import android.util.SparseIntArray
import android.view.View
import androidx.appcompat.widget.AppCompatImageButton
import coil.load
import com.saulhdev.feeder.MainActivity
import com.saulhdev.feeder.R
import com.saulhdev.feeder.databinding.FeedCardStoryLargeBinding
import com.saulhdev.feeder.db.ArticleRepository
import com.saulhdev.feeder.preference.FeedPreferences
import com.saulhdev.feeder.sdk.FeedItem
import com.saulhdev.feeder.theme.Theming
import com.saulhdev.feeder.utils.RelativeTimeHelper
import com.saulhdev.feeder.utils.isDark
import com.saulhdev.feeder.utils.launchView
import com.saulhdev.feeder.utils.urlEncode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object StoryCardBinder : FeedBinder {
override fun bind(theme: SparseIntArray?, item: FeedItem, view: View) {
val context = view.context
val content = item.content
val binding = FeedCardStoryLargeBinding.bind(view)
val prefs = FeedPreferences.getInstance(context)
val repository = ArticleRepository(context)
var bookmarked = item.bookmarked
binding.storyTitle.text = content.title
binding.storySource.text = content.source.title
binding.storyDate.text =
RelativeTimeHelper.getDateFormattedRelative(view.context, (item.time / 1000) - 1000)

if (content.text.isEmpty()) {
binding.storySummary.visibility = View.GONE
} else {
binding.storySummary.text = Html.fromHtml(content.text, 0).toString()
}

if (
content.background_url.isEmpty() ||
content.background_url == "null" ||
content.background_url.contains(".rss")
) {
binding.storyPic.visibility = View.GONE
} else {
binding.storyPic.visibility = View.VISIBLE
binding.storyPic.load(content.background_url) {
crossfade(true)
crossfade(500)
}
}

updateSaveIcon(binding.saveButton, bookmarked)
binding.saveButton.setOnClickListener {
CoroutineScope(Dispatchers.Main).launch {
repository.bookmarkArticle(item.id, !bookmarked)
bookmarked = !bookmarked
updateSaveIcon(binding.saveButton, bookmarked)
}
}

binding.shareButton.setOnClickListener {
val intent = Intent.createChooser(
Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_TEXT, content.link)
putExtra(Intent.EXTRA_TITLE, content.title)
type = "text/plain"
},
null,
)
context.startActivity(intent)
}

binding.root.setOnClickListener {
if (prefs.openInBrowser.getValue()) {
view.context.launchView(content.link)
} else {
val scope = CoroutineScope(Dispatchers.Main)

scope.launch {
if (prefs.offlineReader.getValue()) {
view.context.startActivity(
MainActivity.createIntent(
view.context,
"article_page/${item.id}/"
)
)
} else {
view.context.startActivity(
MainActivity.createIntent(
view.context,
"web_view/${content.link.urlEncode()}/"
)
)
}
}
}
}

theme ?: return
binding.cardStory.setBackgroundColor(theme.get(Theming.Colors.CARD_BG.ordinal))
val themeCard = if (theme.get(Theming.Colors.CARD_BG.ordinal)
.isDark()
) Theming.defaultDarkThemeColors else Theming.defaultLightThemeColors
binding.storyTitle.setTextColor(themeCard.get(Theming.Colors.TEXT_COLOR_PRIMARY.ordinal))
binding.storySource.setTextColor(themeCard.get(Theming.Colors.TEXT_COLOR_SECONDARY.ordinal))
binding.storyDate.setTextColor(themeCard.get(Theming.Colors.TEXT_COLOR_SECONDARY.ordinal))
binding.storySummary.setTextColor(themeCard.get(Theming.Colors.TEXT_COLOR_SECONDARY.ordinal))
}

private fun updateSaveIcon(button: AppCompatImageButton, bookmarked: Boolean) {
if (bookmarked) {
button.setImageResource(R.drawable.ic_heart_fill)
} else {
button.setImageResource(R.drawable.ic_heart)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import android.content.Context
import android.util.SparseIntArray
import androidx.core.content.ContextCompat
import com.saulhdev.feeder.R
import com.saulhdev.feeder.overlay.ComposeOverlayView
import com.saulhdev.feeder.overlay.OverlayView
import com.saulhdev.feeder.preference.FeedPreferences
import com.saulhdev.feeder.theme.Theming
import com.saulhdev.feeder.utils.clearLightFlags

/**
* A class which manages overlay styling.
* */
class OverlayThemeHolder(private val context: Context, private val overlay: ComposeOverlayView) {
class OverlayThemeHolder(private val context: Context, private val overlay: OverlayView) {

val prefs = FeedPreferences.getInstance(context)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,16 @@ import androidx.savedstate.SavedStateRegistryController
import androidx.savedstate.SavedStateRegistryOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
import com.google.android.libraries.gsa.d.a.OverlayController
import com.saulhdev.feeder.NFApplication
import com.saulhdev.feeder.MainActivity
import com.saulhdev.feeder.R
import com.saulhdev.feeder.compose.pages.OverlayPage
import com.saulhdev.feeder.theme.AppTheme
import org.koin.java.KoinJavaComponent.inject

class ComposeOverlayView(val context: Context) :
OverlayController(context, R.style.AppTheme, R.style.WindowTheme),
SavedStateRegistryOwner, ViewModelStoreOwner, OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner {
SavedStateRegistryOwner, ViewModelStoreOwner,
OnBackPressedDispatcherOwner, ActivityResultRegistryOwner {
private lateinit var rootView: View
private lateinit var composeView: ComposeView
private lateinit var navController: NavHostController
Expand All @@ -62,6 +63,8 @@ class ComposeOverlayView(val context: Context) :
override val savedStateRegistry: SavedStateRegistry
get() = savedStateRegistryController.savedStateRegistry

val mainActivity: MainActivity by inject(MainActivity::class.java)

init {
savedStateRegistryController.performAttach()
savedStateRegistryController.performRestore(null)
Expand Down Expand Up @@ -101,7 +104,9 @@ class ComposeOverlayView(val context: Context) :

override val viewModelStore: ViewModelStore
get() = ViewModelStore()

override val activityResultRegistry: ActivityResultRegistry
get() = NFApplication.mainActivity!!.activityResultRegistry
get() = mainActivity.activityResultRegistry
//get() = NFApplication.mainActivity!!.activityResultRegistry

}
Loading

0 comments on commit 44ddea6

Please sign in to comment.