-
Notifications
You must be signed in to change notification settings - Fork 224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
End of Year: Share text #570
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package au.com.shiftyjelly.pocketcasts.endofyear | ||
|
||
import android.content.Context | ||
import au.com.shiftyjelly.pocketcasts.preferences.Settings | ||
import au.com.shiftyjelly.pocketcasts.repositories.endofyear.stories.Story | ||
import au.com.shiftyjelly.pocketcasts.repositories.endofyear.stories.StoryListenedCategories | ||
import au.com.shiftyjelly.pocketcasts.repositories.endofyear.stories.StoryListenedNumbers | ||
import au.com.shiftyjelly.pocketcasts.repositories.endofyear.stories.StoryListeningTime | ||
import au.com.shiftyjelly.pocketcasts.repositories.endofyear.stories.StoryLongestEpisode | ||
import au.com.shiftyjelly.pocketcasts.repositories.endofyear.stories.StoryTopFivePodcasts | ||
import au.com.shiftyjelly.pocketcasts.repositories.endofyear.stories.StoryTopPodcast | ||
import au.com.shiftyjelly.pocketcasts.servers.list.ListServerManager | ||
import au.com.shiftyjelly.pocketcasts.settings.stats.StatsHelper | ||
import dagger.hilt.android.qualifiers.ApplicationContext | ||
import timber.log.Timber | ||
import javax.inject.Inject | ||
import au.com.shiftyjelly.pocketcasts.localization.R as LR | ||
|
||
class ShareableTextProvider @Inject constructor( | ||
@ApplicationContext private val context: Context, | ||
private val listServerManager: ListServerManager, | ||
) { | ||
private var shortURL: String = Settings.SERVER_SHORT_URL | ||
private val hashtags = listOf("pocketcasts", "endofyear2022").joinToString(" ") { "#$it" } | ||
|
||
suspend fun getShareableDataForStory( | ||
story: Story, | ||
): ShareTextData { | ||
var showShortURLAtEnd = false | ||
val shareableLink: String = when (story) { | ||
is StoryTopFivePodcasts -> { | ||
try { | ||
listServerManager.createPodcastList( | ||
title = context.resources.getString( | ||
LR.string.end_of_year_story_top_podcasts_share_text, | ||
"" | ||
), | ||
description = "", | ||
podcasts = story.topPodcasts.map { it.toPodcast() } | ||
) ?: shortURL | ||
} catch (ex: Exception) { | ||
Timber.e(ex) | ||
shortURL | ||
} | ||
} | ||
is StoryTopPodcast -> { | ||
"$shortURL/podcast/${story.topPodcast.uuid}" | ||
} | ||
is StoryLongestEpisode -> { | ||
"$shortURL/episode/${story.longestEpisode.uuid}" | ||
} | ||
else -> { | ||
showShortURLAtEnd = true | ||
shortURL | ||
} | ||
} | ||
val textWithLink = getTextWithLink(story, shareableLink) | ||
return ShareTextData( | ||
textWithLink = textWithLink, | ||
hashTags = hashtags, | ||
showShortURLAtEnd = showShortURLAtEnd | ||
) | ||
} | ||
|
||
private fun getTextWithLink( | ||
story: Story, | ||
shareableLink: String | ||
): String { | ||
val resources = context.resources | ||
return when (story) { | ||
is StoryListeningTime -> { | ||
val timeText = | ||
StatsHelper.secondsToFriendlyString(story.listeningTimeInSecs, resources) | ||
resources.getString( | ||
LR.string.end_of_year_story_listened_to_share_text, | ||
timeText | ||
) | ||
} | ||
|
||
is StoryListenedCategories -> { | ||
resources.getString( | ||
LR.string.end_of_year_story_listened_to_categories_share_text, | ||
story.listenedCategories.size | ||
) | ||
} | ||
|
||
is StoryListenedNumbers -> { | ||
resources.getString( | ||
LR.string.end_of_year_story_listened_to_numbers_share_text, | ||
story.listenedNumbers.numberOfPodcasts, | ||
story.listenedNumbers.numberOfEpisodes | ||
) | ||
} | ||
|
||
is StoryTopPodcast -> { | ||
resources.getString( | ||
LR.string.end_of_year_story_top_podcast_share_text, | ||
shareableLink | ||
) | ||
} | ||
|
||
is StoryTopFivePodcasts -> { | ||
resources.getString( | ||
LR.string.end_of_year_story_top_podcasts_share_text, | ||
shareableLink | ||
) | ||
} | ||
|
||
is StoryLongestEpisode -> { | ||
resources.getString( | ||
LR.string.end_of_year_story_longest_episode_share_text, | ||
shareableLink | ||
) | ||
} | ||
|
||
else -> "" | ||
} | ||
} | ||
|
||
data class ShareTextData( | ||
val textWithLink: String, | ||
val hashTags: String, | ||
val showShortURLAtEnd: Boolean | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ import android.graphics.Bitmap | |
import androidx.annotation.FloatRange | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import au.com.shiftyjelly.pocketcasts.endofyear.ShareableTextProvider.ShareTextData | ||
import au.com.shiftyjelly.pocketcasts.endofyear.StoriesViewModel.State.Loaded.SegmentsData | ||
import au.com.shiftyjelly.pocketcasts.repositories.endofyear.EndOfYearManager | ||
import au.com.shiftyjelly.pocketcasts.repositories.endofyear.stories.Story | ||
|
@@ -25,6 +26,7 @@ import kotlin.math.roundToInt | |
class StoriesViewModel @Inject constructor( | ||
private val endOfYearManager: EndOfYearManager, | ||
private val fileUtilWrapper: FileUtilWrapper, | ||
private val shareableTextProvider: ShareableTextProvider, | ||
) : ViewModel() { | ||
|
||
private val mutableState = MutableStateFlow<State>(State.Loading) | ||
|
@@ -128,8 +130,9 @@ class StoriesViewModel @Inject constructor( | |
|
||
fun onShareClicked( | ||
onCaptureBitmap: () -> Bitmap, | ||
story: Story, | ||
context: Context, | ||
showShareForFile: (File) -> Unit, | ||
showShareForFile: (File, ShareTextData) -> Unit, | ||
) { | ||
pause() | ||
viewModelScope.launch { | ||
|
@@ -139,7 +142,14 @@ class StoriesViewModel @Inject constructor( | |
EOY_STORY_SAVE_FOLDER_NAME, | ||
EOY_STORY_SAVE_FILE_NAME | ||
) | ||
savedFile?.let { showShareForFile.invoke(it) } | ||
|
||
val currentState = (state.value as State.Loaded) | ||
mutableState.value = currentState.copy(preparingShareText = true) | ||
|
||
val shareTextData = shareableTextProvider.getShareableDataForStory(story) | ||
mutableState.value = currentState.copy(preparingShareText = false) | ||
Comment on lines
+146
to
+150
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if there's any way the state could get mutated while we're waiting for the suspended device-2022-11-14-112608.mp4There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is because This SO answer helped me understand it:
Feature request: https://issuetracker.google.com/issues/165642391 I'll open another PR with a fix or temporary workaround. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think that disabling the UI as soon as the Share button is touched might help? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I switched to |
||
|
||
savedFile?.let { showShareForFile.invoke(it, shareTextData) } | ||
} | ||
} | ||
|
||
|
@@ -183,6 +193,7 @@ class StoriesViewModel @Inject constructor( | |
data class Loaded( | ||
val currentStory: Story?, | ||
val segmentsData: SegmentsData, | ||
val preparingShareText: Boolean = false, | ||
) : State() { | ||
data class SegmentsData( | ||
val widths: List<Float> = emptyList(), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This api call failed for me with a 403 everytime I tried to share the top 5 podcasts, so I fell through to the generic PC link each time. Not sure what is causing that. I tried both logged-in and logged-out on the staging and prod server with the same result each time. π€
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you confirm if you can share podcasts and episodes in general (from podcasts or episode fragments)?
I'll merge this PR for now. Based on your response, I'll recheck what might be going wrong with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. I'm also getting an error when I try to create a shared list of podcasts from the podcasts page, so I don't think this is an issue with your EOY work (and fwiw, I can share a list with our current production builds, so I must be doing something weird locally).