Skip to content

Commit

Permalink
6.9.1 commit
Browse files Browse the repository at this point in the history
  • Loading branch information
XilinJia committed Oct 7, 2024
1 parent 181aa76 commit ceb6979
Show file tree
Hide file tree
Showing 28 changed files with 769 additions and 886 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ android {
testApplicationId "ac.mdiq.podcini.tests"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

versionCode 3020265
versionName "6.9.0"
versionCode 3020266
versionName "6.9.1"

applicationId "ac.mdiq.podcini.R"
def commit = ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import ac.mdiq.podcini.ui.activity.MainActivity
import ac.mdiq.podcini.ui.activity.PreferenceActivity
import ac.mdiq.podcini.ui.fragment.*
import ac.mdiq.podcini.preferences.UserPreferences.hiddenDrawerItems
import ac.mdiq.podcini.ui.fragment.NavDrawerFragment.Companion.navMap
import de.test.podcini.EspressoTestUtils
import de.test.podcini.NthMatcher
import org.hamcrest.Matchers
Expand Down Expand Up @@ -174,7 +175,8 @@ class NavigationDrawerTest {
fun testDrawerPreferencesHideAllElements() {
hiddenDrawerItems = ArrayList()
activityRule.launchActivity(Intent())
val titles = activityRule.activity.resources.getStringArray(R.array.nav_drawer_titles)
// val titles = activityRule.activity.resources.getStringArray(R.array.nav_drawer_titles)
val titles = navMap.keys.toTypedArray()

openNavDrawer()
Espresso.onView(NthMatcher.first(ViewMatchers.withText(R.string.queue_label))).perform(ViewActions.longClick())
Expand All @@ -192,7 +194,7 @@ class NavigationDrawerTest {

val hidden = hiddenDrawerItems
Assert.assertEquals(titles.size.toLong(), hidden!!.size.toLong())
for (tag in NavDrawerFragment.NAV_DRAWER_TAGS) {
for (tag in NavDrawerFragment.navMap.keys) {
Assert.assertTrue(hidden.contains(tag))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package ac.mdiq.podcini.preferences.fragments

import ac.mdiq.podcini.R
import ac.mdiq.podcini.preferences.UserPreferences
import ac.mdiq.podcini.preferences.UserPreferences.defaultPage
import ac.mdiq.podcini.preferences.UserPreferences.fullNotificationButtons
import ac.mdiq.podcini.preferences.UserPreferences.hiddenDrawerItems
import ac.mdiq.podcini.preferences.UserPreferences.setShowRemainTimeSetting
import ac.mdiq.podcini.ui.activity.PreferenceActivity
import ac.mdiq.podcini.ui.dialog.DrawerPreferencesDialog
import ac.mdiq.podcini.ui.dialog.FeedSortDialog
import ac.mdiq.podcini.ui.fragment.NavDrawerFragment.Companion.navMap
import ac.mdiq.podcini.util.EventFlow
import ac.mdiq.podcini.util.FlowEvent
import ac.mdiq.podcini.util.Logd
import android.content.Context
import android.content.DialogInterface
import android.os.Build
Expand Down Expand Up @@ -50,8 +53,39 @@ class UserInterfacePreferencesFragment : PreferenceFragmentCompat() {
true
}

fun drawerPreferencesDialog(context: Context, callback: Runnable?) {
val hiddenItems = hiddenDrawerItems.map { it.trim() }.toMutableSet()
// val navTitles = context.resources.getStringArray(R.array.nav_drawer_titles)
val navTitles = navMap.values.map { context.resources.getString(it.nameRes).trim() }.toTypedArray()
val checked = BooleanArray(navMap.size)
for (i in navMap.keys.indices) {
val tag = navMap.keys.toList()[i]
if (!hiddenItems.contains(tag)) checked[i] = true
}
val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(R.string.drawer_preferences)
builder.setMultiChoiceItems(navTitles, checked) { _: DialogInterface?, which: Int, isChecked: Boolean ->
if (isChecked) hiddenItems.remove(navMap.keys.toList()[which])
else hiddenItems.add((navMap.keys.toList()[which]).trim())
}
builder.setPositiveButton(R.string.confirm_label) { _: DialogInterface?, _: Int ->
hiddenDrawerItems = hiddenItems.toList()
if (hiddenItems.contains(defaultPage)) {
for (tag in navMap.keys) {
if (!hiddenItems.contains(tag)) {
defaultPage = tag
break
}
}
}
callback?.run()
}
builder.setNegativeButton(R.string.cancel_label, null)
builder.create().show()
}

findPreference<Preference>(UserPreferences.Prefs.prefHiddenDrawerItems.name)?.setOnPreferenceClickListener {
DrawerPreferencesDialog.show(requireContext(), null)
drawerPreferencesDialog(requireContext(), null)
true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import kotlin.coroutines.ContinuationInterceptor
object RealmDB {
private val TAG: String = RealmDB::class.simpleName ?: "Anonymous"

private const val SCHEMA_VERSION_NUMBER = 22L
private const val SCHEMA_VERSION_NUMBER = 24L

private val ioScope = CoroutineScope(Dispatchers.IO)

Expand All @@ -35,6 +35,7 @@ object RealmDB {
CurrentState::class,
PlayQueue::class,
DownloadResult::class,
ShareLog::class,
Chapter::class))
.name("Podcini.realm")
.schemaVersion(SCHEMA_VERSION_NUMBER)
Expand Down

This file was deleted.

5 changes: 3 additions & 2 deletions app/src/main/kotlin/ac/mdiq/podcini/storage/model/Episode.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package ac.mdiq.podcini.storage.model

import ac.mdiq.podcini.net.download.DownloadStatus
import ac.mdiq.podcini.storage.database.Feeds.getFeed
import ac.mdiq.vista.extractor.Vista
import ac.mdiq.vista.extractor.stream.StreamInfo
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.ext.realmSetOf
Expand Down Expand Up @@ -87,6 +85,9 @@ class Episode : RealmObject {

var isFavorite: Boolean = false

// 0 : neutral, -1 : dislike, 1 : like
var opinion: Int = 0

@Ignore
val isNew: Boolean
get() = playState == PlayState.NEW.code
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/kotlin/ac/mdiq/podcini/storage/model/Feed.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class Feed : RealmObject {
*/
var lastUpdate: String? = null

// recorded when an episode starts playing when FeedEpisodes is open
var lastPlayed: Long = 0
/**
* Feed type, options are defined in [FeedType].
*/
Expand Down
25 changes: 25 additions & 0 deletions app/src/main/kotlin/ac/mdiq/podcini/storage/model/ShareLog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ac.mdiq.podcini.storage.model

import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey
import java.util.Date

class ShareLog : RealmObject {
@PrimaryKey
var id: Long = 0L // this is the Date

var url: String? = null

var type: String? = null

var status: Int = 0

var details: String = ""

constructor() {}

constructor(url: String) {
id = Date().time
this.url = url
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class MainActivity : CastEnabledActivity() {
if (UserPreferences.DEFAULT_PAGE_REMEMBER != defaultPage) loadFragment(defaultPage, null)
else {
val lastFragment = NavDrawerFragment.getLastNavFragment()
if (ArrayUtils.contains(NavDrawerFragment.NAV_DRAWER_TAGS, lastFragment)) loadFragment(lastFragment, null)
if (NavDrawerFragment.navMap.keys.contains(lastFragment)) loadFragment(lastFragment, null)
else {
// it's not a number, this happens if we removed a label from the NAV_DRAWER_TAGS give them a nice default...
try { loadFeedFragmentById(lastFragment.toInt().toLong(), null) }
Expand Down Expand Up @@ -419,10 +419,12 @@ class MainActivity : CastEnabledActivity() {
QueuesFragment.TAG -> fragment = QueuesFragment()
AllEpisodesFragment.TAG -> fragment = AllEpisodesFragment()
DownloadsFragment.TAG -> fragment = DownloadsFragment()
SharedLogFragment.TAG -> fragment = SharedLogFragment()
HistoryFragment.TAG -> fragment = HistoryFragment()
OnlineSearchFragment.TAG -> fragment = OnlineSearchFragment()
SubscriptionsFragment.TAG -> fragment = SubscriptionsFragment()
StatisticsFragment.TAG -> fragment = StatisticsFragment()
FeedEpisodesFragment.TAG -> fragment = FeedEpisodesFragment()
else -> {
// default to subscriptions screen
fragment = SubscriptionsFragment()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package ac.mdiq.podcini.ui.activity

import ac.mdiq.podcini.R
import ac.mdiq.podcini.storage.database.RealmDB.realm
import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
import ac.mdiq.podcini.storage.model.ShareLog
import ac.mdiq.podcini.ui.compose.CustomTheme
import ac.mdiq.podcini.ui.compose.confirmAddYoutubeEpisode
import ac.mdiq.podcini.util.Logd
Expand All @@ -27,6 +30,7 @@ class ShareReceiverActivity : AppCompatActivity() {
@OptIn(UnstableApi::class) override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

Logd(TAG, "intent: $intent")
when {
intent.hasExtra(ARG_FEEDURL) -> sharedUrl = intent.getStringExtra(ARG_FEEDURL)
intent.action == Intent.ACTION_SEND -> sharedUrl = intent.getStringExtra(Intent.EXTRA_TEXT)
Expand All @@ -43,77 +47,45 @@ class ShareReceiverActivity : AppCompatActivity() {
if (urlString != null) sharedUrl = URLDecoder.decode(urlString, "UTF-8")
}
Logd(TAG, "feedUrl: $sharedUrl")
val url = URL(sharedUrl)
when {
// plain text
sharedUrl!!.matches(Regex("^[^\\s<>/]+\$")) -> {
val intent = MainActivity.showOnlineSearch(this, sharedUrl!!)
startActivity(intent)
finish()
}
// Youtube media
// sharedUrl!!.startsWith("https://youtube.com/watch?") || sharedUrl!!.startsWith("https://www.youtube.com/watch?") || sharedUrl!!.startsWith("https://music.youtube.com/watch?") -> {
(isYoutubeURL(url) && url.path.startsWith("/watch")) || isYoutubeServiceURL(url) -> {
Logd(TAG, "got youtube media")
setContent {
val showDialog = remember { mutableStateOf(true) }
CustomTheme(this@ShareReceiverActivity) {
confirmAddYoutubeEpisode(listOf(sharedUrl!!), showDialog.value, onDismissRequest = {
showDialog.value = false
finish()
})
}
}
}
// podcast or Youtube channel, Youtube playlist, or other?
else -> {
Logd(TAG, "Activity was started with url $sharedUrl")
val intent = MainActivity.showOnlineFeed(this, sharedUrl!!)
// intent.putExtra(MainActivity.Extras.started_from_share.name, getIntent().getBooleanExtra(MainActivity.Extras.started_from_share.name, false))
startActivity(intent)
finish()
}
}
}
val log = ShareLog(sharedUrl!!)
upsertBlk(log) {}
receiveShared(sharedUrl!!,this, true)

// @Composable
// fun confirmAddEpisode(sharedUrl: String, showDialog: Boolean, onDismissRequest: () -> Unit) {
// var showToast by remember { mutableStateOf(false) }
// var toastMassege by remember { mutableStateOf("")}
// if (showToast) CustomToast(message = toastMassege, onDismiss = { showToast = false })
//
// if (showDialog) {
// Dialog(onDismissRequest = { onDismissRequest() }) {
// Card(modifier = Modifier.wrapContentSize(align = Alignment.Center).padding(16.dp), shape = RoundedCornerShape(16.dp)) {
// Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.Center) {
// var audioOnly by remember { mutableStateOf(false) }
// Row(Modifier.fillMaxWidth()) {
// Checkbox(checked = audioOnly, onCheckedChange = { audioOnly = it })
// Text(text = stringResource(R.string.pref_video_mode_audio_only), style = MaterialTheme.typography.bodyLarge.merge())
// }
// Button(onClick = {
// CoroutineScope(Dispatchers.IO).launch {
// try {
// val info = StreamInfo.getInfo(Vista.getService(0), sharedUrl)
// Logd(TAG, "info: $info")
// val episode = episodeFromStreamInfo(info)
// Logd(TAG, "episode: $episode")
// addToYoutubeSyndicate(episode, !audioOnly)
// } catch (e: Throwable) {
// toastMassege = "Receive share error: ${e.message}"
// Log.e(TAG, toastMassege)
// showToast = true
// }
// }
// onDismissRequest()
// }) {
// Text("Confirm")
// }
// val url = URL(sharedUrl)
// when {
//// plain text
// sharedUrl!!.matches(Regex("^[^\\s<>/]+\$")) -> {
// log = upsertBlk(log) {it.type = "text" }
// val intent = MainActivity.showOnlineSearch(this, sharedUrl!!)
// startActivity(intent)
// finish()
// }
//// Youtube media
//// sharedUrl!!.startsWith("https://youtube.com/watch?") || sharedUrl!!.startsWith("https://www.youtube.com/watch?") || sharedUrl!!.startsWith("https://music.youtube.com/watch?") -> {
// (isYoutubeURL(url) && url.path.startsWith("/watch")) || isYoutubeServiceURL(url) -> {
// log = upsertBlk(log) {it.type = "youtube media" }
// Logd(TAG, "got youtube media")
// setContent {
// val showDialog = remember { mutableStateOf(true) }
// CustomTheme(this@ShareReceiverActivity) {
// confirmAddYoutubeEpisode(listOf(sharedUrl!!), showDialog.value, onDismissRequest = {
// showDialog.value = false
// finish()
// })
// }
// }
// }
//// podcast or Youtube channel, Youtube playlist, or other?
// else -> {
// log = upsertBlk(log) {it.type = "podcast" }
// Logd(TAG, "Activity was started with url $sharedUrl")
// val intent = MainActivity.showOnlineFeed(this, sharedUrl!!)
//// intent.putExtra(MainActivity.Extras.started_from_share.name, getIntent().getBooleanExtra(MainActivity.Extras.started_from_share.name, false))
// startActivity(intent)
// finish()
// }
// }
// }
}

private fun showNoPodcastFoundError() {
runOnUiThread {
Expand All @@ -138,5 +110,41 @@ class ShareReceiverActivity : AppCompatActivity() {

const val ARG_FEEDURL: String = "arg.feedurl"
private const val RESULT_ERROR = 2

fun receiveShared(sharedUrl: String, activity: AppCompatActivity, finish: Boolean) {
val url = URL(sharedUrl)
val log = realm.query(ShareLog::class).query("url == $0", sharedUrl).first().find()
when {
// plain text
sharedUrl.matches(Regex("^[^\\s<>/]+\$")) -> {
if (log != null) upsertBlk(log) {it.type = "text" }
val intent = MainActivity.showOnlineSearch(activity, sharedUrl)
activity.startActivity(intent)
if (finish) activity.finish()
}
// Youtube media
(isYoutubeURL(url) && url.path.startsWith("/watch")) || isYoutubeServiceURL(url) -> {
if (log != null) upsertBlk(log) {it.type = "youtube media" }
Logd(TAG, "got youtube media")
activity.setContent {
val showDialog = remember { mutableStateOf(true) }
CustomTheme(activity) {
confirmAddYoutubeEpisode(listOf(sharedUrl), showDialog.value, onDismissRequest = {
showDialog.value = false
if (finish) activity.finish()
})
}
}
}
// podcast or Youtube channel, Youtube playlist, or other?
else -> {
if (log != null) upsertBlk(log) {it.type = "podcast" }
Logd(TAG, "Activity was started with url $sharedUrl")
val intent = MainActivity.showOnlineFeed(activity, sharedUrl)
activity.startActivity(intent)
if (finish) activity.finish()
}
}
}
}
}
Loading

0 comments on commit ceb6979

Please sign in to comment.