forked from recloudstream/cloudstream
		
	fuck android (((also fixes)))
This commit is contained in:
		
							parent
							
								
									ef91102daf
								
							
						
					
					
						commit
						486cea39c5
					
				
					 16 changed files with 248 additions and 229 deletions
				
			
		|  | @ -31,7 +31,7 @@ | ||||||
|         <activity |         <activity | ||||||
|                 android:exported="true" |                 android:exported="true" | ||||||
|                 android:name=".MainActivity" |                 android:name=".MainActivity" | ||||||
|                 android:configChanges="screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|navigation" |                 android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|navigation" | ||||||
|                 android:label="@string/app_name" |                 android:label="@string/app_name" | ||||||
|                 android:resizeableActivity="true" |                 android:resizeableActivity="true" | ||||||
|                 android:supportsPictureInPicture="true"> |                 android:supportsPictureInPicture="true"> | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ import androidx.annotation.StringRes | ||||||
| import androidx.appcompat.app.AppCompatActivity | import androidx.appcompat.app.AppCompatActivity | ||||||
| import androidx.appcompat.widget.SearchView | import androidx.appcompat.widget.SearchView | ||||||
| import androidx.core.view.isVisible | import androidx.core.view.isVisible | ||||||
|  | import androidx.navigation.NavDestination | ||||||
| import androidx.navigation.findNavController | import androidx.navigation.findNavController | ||||||
| import androidx.navigation.ui.setupWithNavController | import androidx.navigation.ui.setupWithNavController | ||||||
| import androidx.preference.PreferenceManager | import androidx.preference.PreferenceManager | ||||||
|  | @ -87,6 +88,38 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | ||||||
|     override fun onConfigurationChanged(newConfig: Configuration) { |     override fun onConfigurationChanged(newConfig: Configuration) { | ||||||
|         super.onConfigurationChanged(newConfig) |         super.onConfigurationChanged(newConfig) | ||||||
|         updateLocale() // android fucks me by chaining lang when rotating the phone |         updateLocale() // android fucks me by chaining lang when rotating the phone | ||||||
|  |         findNavController(R.id.nav_host_fragment).currentDestination?.let { updateNavBar(it) } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun updateNavBar(destination : NavDestination) { | ||||||
|  |         this.hideKeyboard() | ||||||
|  | 
 | ||||||
|  |         // Fucks up anime info layout since that has its own layout | ||||||
|  |         cast_mini_controller_holder?.isVisible = | ||||||
|  |             !listOf(R.id.navigation_results, R.id.navigation_player).contains(destination.id) | ||||||
|  | 
 | ||||||
|  |         val isNavVisible = listOf( | ||||||
|  |             R.id.navigation_home, | ||||||
|  |             R.id.navigation_search, | ||||||
|  |             R.id.navigation_downloads, | ||||||
|  |             R.id.navigation_settings, | ||||||
|  |             R.id.navigation_download_child | ||||||
|  |         ).contains(destination.id) | ||||||
|  | 
 | ||||||
|  |         val landscape = when(resources.configuration.orientation) { | ||||||
|  |             Configuration.ORIENTATION_LANDSCAPE -> { | ||||||
|  |                 true | ||||||
|  |             } | ||||||
|  |             Configuration.ORIENTATION_PORTRAIT -> { | ||||||
|  |                 false | ||||||
|  |             } | ||||||
|  |             else -> { | ||||||
|  |                 false | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         nav_view?.isVisible = isNavVisible && !landscape | ||||||
|  |         nav_rail_view?.isVisible = isNavVisible && landscape | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //private var mCastSession: CastSession? = null |     //private var mCastSession: CastSession? = null | ||||||
|  | @ -553,30 +586,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | ||||||
|         val navRail = findViewById<NavigationRailView?>(R.id.nav_rail_view) |         val navRail = findViewById<NavigationRailView?>(R.id.nav_rail_view) | ||||||
|         navRail?.setupWithNavController(navController) |         navRail?.setupWithNavController(navController) | ||||||
|         navController.addOnDestinationChangedListener { _, destination, _ -> |         navController.addOnDestinationChangedListener { _, destination, _ -> | ||||||
|             this.hideKeyboard() |             updateNavBar(destination) | ||||||
|             // nav_view.hideKeyboard() |  | ||||||
|             /*if (destination.id != R.id.navigation_player) { |  | ||||||
|                 requestedOrientation = if (settingsManager?.getBoolean("force_landscape", false) == true) { |  | ||||||
|                     ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE |  | ||||||
|                 } else { |  | ||||||
|                     ActivityInfo.SCREEN_ORIENTATION_PORTRAIT |  | ||||||
|                 } |  | ||||||
|             }*/ |  | ||||||
| 
 |  | ||||||
|             // Fucks up anime info layout since that has its own layout |  | ||||||
|             cast_mini_controller_holder?.isVisible = |  | ||||||
|                 !listOf(R.id.navigation_results, R.id.navigation_player).contains(destination.id) |  | ||||||
| 
 |  | ||||||
|             val isNavVisible = listOf( |  | ||||||
|                 R.id.navigation_home, |  | ||||||
|                 R.id.navigation_search, |  | ||||||
|                 R.id.navigation_downloads, |  | ||||||
|                 R.id.navigation_settings, |  | ||||||
|                 R.id.navigation_download_child |  | ||||||
|             ).contains(destination.id) |  | ||||||
| 
 |  | ||||||
|             nav_view?.isVisible = isNavVisible |  | ||||||
|             navRail?.isVisible = isNavVisible |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /*nav_view.setOnNavigationItemSelectedListener { item -> |         /*nav_view.setOnNavigationItemSelectedListener { item -> | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ import com.lagradost.cloudstream3.utils.CastHelper.awaitLinks | ||||||
| import com.lagradost.cloudstream3.utils.CastHelper.getMediaInfo | import com.lagradost.cloudstream3.utils.CastHelper.getMediaInfo | ||||||
| import com.lagradost.cloudstream3.utils.DataStore.toKotlinObject | import com.lagradost.cloudstream3.utils.DataStore.toKotlinObject | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe | ||||||
| import org.json.JSONObject | import org.json.JSONObject | ||||||
| import kotlin.concurrent.thread | import kotlin.concurrent.thread | ||||||
| 
 | 
 | ||||||
|  | @ -156,7 +157,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi | ||||||
|                                         } |                                         } | ||||||
|                                     } |                                     } | ||||||
|                             } |                             } | ||||||
|                             bottomSheetDialog.dismiss() |                             bottomSheetDialog.dismissSafe(activity) | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|  | @ -220,9 +221,8 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi | ||||||
|                         } |                         } | ||||||
|                         loadMirror(which) |                         loadMirror(which) | ||||||
| 
 | 
 | ||||||
|                         bottomSheetDialog.dismiss() |                         bottomSheetDialog.dismissSafe(activity) | ||||||
|                     } |                     } | ||||||
| 
 |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ import android.widget.Toast | ||||||
| import androidx.appcompat.app.AlertDialog | import androidx.appcompat.app.AlertDialog | ||||||
| import com.lagradost.cloudstream3.MainActivity | import com.lagradost.cloudstream3.MainActivity | ||||||
| import com.lagradost.cloudstream3.R | import com.lagradost.cloudstream3.R | ||||||
|  | import com.lagradost.cloudstream3.mvvm.logError | ||||||
| import com.lagradost.cloudstream3.ui.player.PlayerFragment | import com.lagradost.cloudstream3.ui.player.PlayerFragment | ||||||
| import com.lagradost.cloudstream3.ui.player.UriData | import com.lagradost.cloudstream3.ui.player.UriData | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.getNameFull | import com.lagradost.cloudstream3.utils.AppUtils.getNameFull | ||||||
|  | @ -34,19 +35,24 @@ object DownloadButtonSetup { | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                     builder.setTitle(R.string.delete_file) |                     try { | ||||||
|                         .setMessage( |                         builder.setTitle(R.string.delete_file) | ||||||
|                             ctx.getString(R.string.delete_message).format( |                             .setMessage( | ||||||
|                                 ctx.getNameFull( |                                 ctx.getString(R.string.delete_message).format( | ||||||
|                                     click.data.name, |                                     ctx.getNameFull( | ||||||
|                                     click.data.episode, |                                         click.data.name, | ||||||
|                                     click.data.season |                                         click.data.episode, | ||||||
|  |                                         click.data.season | ||||||
|  |                                     ) | ||||||
|                                 ) |                                 ) | ||||||
|                             ) |                             ) | ||||||
|                         ) |                             .setPositiveButton(R.string.delete, dialogClickListener) | ||||||
|                         .setPositiveButton(R.string.delete, dialogClickListener) |                             .setNegativeButton(R.string.cancel, dialogClickListener) | ||||||
|                         .setNegativeButton(R.string.cancel, dialogClickListener) |                             .show() | ||||||
|                         .show() |                     } catch (e : Exception) { | ||||||
|  |                         logError(e) | ||||||
|  |                         // ye you somehow fucked up formatting did you? | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> { |             DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> { | ||||||
|  |  | ||||||
|  | @ -45,6 +45,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.removeLastWatched | ||||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState | import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState | ||||||
| import com.lagradost.cloudstream3.utils.Event | import com.lagradost.cloudstream3.utils.Event | ||||||
| import com.lagradost.cloudstream3.utils.HOMEPAGE_API | import com.lagradost.cloudstream3.utils.HOMEPAGE_API | ||||||
|  | import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbarView | import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbarView | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact | import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact | ||||||
|  | @ -52,6 +53,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes | import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.setImage | import com.lagradost.cloudstream3.utils.UIHelper.setImage | ||||||
| import com.lagradost.cloudstream3.widget.CenterZoomLayoutManager | import com.lagradost.cloudstream3.widget.CenterZoomLayoutManager | ||||||
|  | import kotlinx.android.synthetic.main.activity_main.* | ||||||
| import kotlinx.android.synthetic.main.fragment_home.* | import kotlinx.android.synthetic.main.fragment_home.* | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
|  | @ -72,7 +74,7 @@ class HomeFragment : Fragment() { | ||||||
|             val titleHolder = bottomSheetDialogBuilder.findViewById<FrameLayout>(R.id.home_expanded_drag_down)!! |             val titleHolder = bottomSheetDialogBuilder.findViewById<FrameLayout>(R.id.home_expanded_drag_down)!! | ||||||
| 
 | 
 | ||||||
|             titleHolder.setOnClickListener { |             titleHolder.setOnClickListener { | ||||||
|                 bottomSheetDialogBuilder.dismiss() |                 bottomSheetDialogBuilder.dismissSafe(this) | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Span settings |             // Span settings | ||||||
|  | @ -81,7 +83,7 @@ class HomeFragment : Fragment() { | ||||||
|             recycle.adapter = SearchAdapter(item.list, recycle) { callback -> |             recycle.adapter = SearchAdapter(item.list, recycle) { callback -> | ||||||
|                 handleSearchClickCallback(this, callback) |                 handleSearchClickCallback(this, callback) | ||||||
|                 if (callback.action == SEARCH_ACTION_LOAD || callback.action == SEARCH_ACTION_PLAY_FILE) { |                 if (callback.action == SEARCH_ACTION_LOAD || callback.action == SEARCH_ACTION_PLAY_FILE) { | ||||||
|                     bottomSheetDialogBuilder.dismiss() |                     bottomSheetDialogBuilder.dismissSafe(this) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -88,6 +88,7 @@ import com.lagradost.cloudstream3.utils.DataStore.setKey | ||||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.setLastWatched | import com.lagradost.cloudstream3.utils.DataStoreHelper.setLastWatched | ||||||
| import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog | import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute | import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute | ||||||
|  | import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.getNavigationBarHeight | import com.lagradost.cloudstream3.utils.UIHelper.getNavigationBarHeight | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.getStatusBarHeight | import com.lagradost.cloudstream3.utils.UIHelper.getStatusBarHeight | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | ||||||
|  | @ -125,12 +126,12 @@ const val OPENING_PERCENTAGE = 50 | ||||||
| const val AUTOLOAD_NEXT_EPISODE_PERCENTAGE = 80 | const val AUTOLOAD_NEXT_EPISODE_PERCENTAGE = 80 | ||||||
| 
 | 
 | ||||||
| enum class PlayerEventType(val value: Int) { | enum class PlayerEventType(val value: Int) { | ||||||
|     Stop(-1), |     //Stop(-1), | ||||||
|     Pause(0), |     Pause(0), | ||||||
|     Play(1), |     Play(1), | ||||||
|     SeekForward(2), |     SeekForward(2), | ||||||
|     SeekBack(3), |     SeekBack(3), | ||||||
|     SkipCurrentChapter(4), |     //SkipCurrentChapter(4), | ||||||
|     NextEpisode(5), |     NextEpisode(5), | ||||||
|     PrevEpisode(5), |     PrevEpisode(5), | ||||||
|     PlayPauseToggle(7), |     PlayPauseToggle(7), | ||||||
|  | @ -1189,11 +1190,11 @@ class PlayerFragment : Fragment() { | ||||||
|                         listOf(0.5f, 0.75f, 0.85f, 1f, 1.15f, 1.25f, 1.4f, 1.5f, 1.75f, 2f) |                         listOf(0.5f, 0.75f, 0.85f, 1f, 1.15f, 1.25f, 1.4f, 1.5f, 1.75f, 2f) | ||||||
|                     val speedIndex = speedsNumbers.indexOf(playbackSpeed) |                     val speedIndex = speedsNumbers.indexOf(playbackSpeed) | ||||||
| 
 | 
 | ||||||
|                     context?.let { ctx -> |                     activity?.let { act -> | ||||||
|                         ctx.showDialog( |                         act.showDialog( | ||||||
|                             speedsText, |                             speedsText, | ||||||
|                             speedIndex, |                             speedIndex, | ||||||
|                             ctx.getString(R.string.player_speed), |                             act.getString(R.string.player_speed), | ||||||
|                             false, |                             false, | ||||||
|                             { |                             { | ||||||
|                                 activity?.hideSystemUI() |                                 activity?.hideSystemUI() | ||||||
|  | @ -1236,7 +1237,7 @@ class PlayerFragment : Fragment() { | ||||||
|                             autoHide() |                             autoHide() | ||||||
|                             saveArguments() |                             saveArguments() | ||||||
|                             SubtitlesFragment.push(activity) |                             SubtitlesFragment.push(activity) | ||||||
|                             sourceDialog.dismiss() |                             sourceDialog.dismissSafe(activity) | ||||||
|                         } |                         } | ||||||
|                         var sourceIndex = 0 |                         var sourceIndex = 0 | ||||||
|                         var startSource = 0 |                         var startSource = 0 | ||||||
|  | @ -1297,7 +1298,7 @@ class PlayerFragment : Fragment() { | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         cancelButton.setOnClickListener { |                         cancelButton.setOnClickListener { | ||||||
|                             sourceDialog.dismiss() |                             sourceDialog.dismissSafe(activity) | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         applyButton.setOnClickListener { |                         applyButton.setOnClickListener { | ||||||
|  | @ -1324,7 +1325,7 @@ class PlayerFragment : Fragment() { | ||||||
|                             if (init) { |                             if (init) { | ||||||
|                                 initPlayer(getCurrentUrl()) |                                 initPlayer(getCurrentUrl()) | ||||||
|                             } |                             } | ||||||
|                             sourceDialog.dismiss() |                             sourceDialog.dismissSafe(activity) | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | @ -1796,11 +1797,15 @@ class PlayerFragment : Fragment() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun getCurrentUrl(): ExtractorLink? { |     private fun getCurrentUrl(): ExtractorLink? { | ||||||
|         val urls = getUrls() ?: return null |         try { | ||||||
|         for (i in urls) { |             val urls = getUrls() ?: return null | ||||||
|             if (i.getId() == playerData.mirrorId) { |             for (i in urls) { | ||||||
|                 return i |                 if (i.getId() == playerData.mirrorId) { | ||||||
|  |                     return i | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |         } catch (e : Exception) { | ||||||
|  |             return null | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return null |         return null | ||||||
|  | @ -2189,11 +2194,11 @@ class PlayerFragment : Fragment() { | ||||||
|                 setUpstreamDataSourceFactory(getDataSourceFactory()) |                 setUpstreamDataSourceFactory(getDataSourceFactory()) | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             val _exoPlayer = |             val exoPlayerBuilder = | ||||||
|                 ExoPlayer.Builder(requireContext()) |                 ExoPlayer.Builder(requireContext()) | ||||||
|                     .setTrackSelector(trackSelector) |                     .setTrackSelector(trackSelector) | ||||||
| 
 | 
 | ||||||
|             exoPlayer = _exoPlayer.build().apply { |             exoPlayer = exoPlayerBuilder.build().apply { | ||||||
|                 playWhenReady = isPlayerPlaying |                 playWhenReady = isPlayerPlaying | ||||||
|                 seekTo(currentWindow, playbackPosition) |                 seekTo(currentWindow, playbackPosition) | ||||||
|                 setMediaSource( |                 setMediaSource( | ||||||
|  |  | ||||||
|  | @ -61,6 +61,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos | ||||||
| import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog | import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.checkWrite | import com.lagradost.cloudstream3.utils.UIHelper.checkWrite | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute | import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute | ||||||
|  | import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.navigate | import com.lagradost.cloudstream3.utils.UIHelper.navigate | ||||||
|  | @ -393,7 +394,7 @@ class ResultFragment : Fragment() { | ||||||
| 
 | 
 | ||||||
|                 val data = viewModel.loadEpisode(episodeClick.data, isCasting) |                 val data = viewModel.loadEpisode(episodeClick.data, isCasting) | ||||||
|                 if (currentLoadingCount != currentLoad) return false |                 if (currentLoadingCount != currentLoad) return false | ||||||
|                 loadingDialog?.dismiss() |                 loadingDialog?.dismissSafe(activity) | ||||||
| 
 | 
 | ||||||
|                 when (data) { |                 when (data) { | ||||||
|                     is Resource.Success -> { |                     is Resource.Success -> { | ||||||
|  | @ -627,7 +628,7 @@ class ResultFragment : Fragment() { | ||||||
|                             verifiedOptions.toTypedArray() |                             verifiedOptions.toTypedArray() | ||||||
|                         ) { _, which -> |                         ) { _, which -> | ||||||
|                             handleAction(EpisodeClickEvent(verifiedOptionsValues[which], episodeClick.data)) |                             handleAction(EpisodeClickEvent(verifiedOptionsValues[which], episodeClick.data)) | ||||||
|                             dialog?.dismiss() |                             dialog?.dismissSafe(activity) | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         dialog = builder.create() |                         dialog = builder.create() | ||||||
|  | @ -636,13 +637,18 @@ class ResultFragment : Fragment() { | ||||||
|                 } |                 } | ||||||
|                 ACTION_COPY_LINK -> { |                 ACTION_COPY_LINK -> { | ||||||
|                     activity?.let { act -> |                     activity?.let { act -> | ||||||
|                         acquireSingeExtractorLink(act.getString(R.string.episode_action_copy_link)) { link -> |                         try { | ||||||
|                             val serviceClipboard = |                             acquireSingeExtractorLink(act.getString(R.string.episode_action_copy_link)) { link -> | ||||||
|                                 (act.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager?) |                                 val serviceClipboard = | ||||||
|                                     ?: return@acquireSingeExtractorLink |                                     (act.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager?) | ||||||
|                             val clip = ClipData.newPlainText(link.name, link.url) |                                         ?: return@acquireSingeExtractorLink | ||||||
|                             serviceClipboard.setPrimaryClip(clip) |                                 val clip = ClipData.newPlainText(link.name, link.url) | ||||||
|                             showToast(act, R.string.copy_link_toast, Toast.LENGTH_SHORT) |                                 serviceClipboard.setPrimaryClip(clip) | ||||||
|  |                                 showToast(act, R.string.copy_link_toast, Toast.LENGTH_SHORT) | ||||||
|  |                             } | ||||||
|  |                         } catch (e: Exception) { | ||||||
|  |                             showToast(act, e.toString(), Toast.LENGTH_LONG) | ||||||
|  |                             logError(e) | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | @ -668,58 +674,63 @@ class ResultFragment : Fragment() { | ||||||
| 
 | 
 | ||||||
|                 ACTION_PLAY_EPISODE_IN_VLC_PLAYER -> { |                 ACTION_PLAY_EPISODE_IN_VLC_PLAYER -> { | ||||||
|                     activity?.let { act -> |                     activity?.let { act -> | ||||||
|                         if (!act.checkWrite()) { |                         try { | ||||||
|                             act.requestRW() |                             if (!act.checkWrite()) { | ||||||
|                             if (act.checkWrite()) return@main |                                 act.requestRW() | ||||||
|                         } |                                 if (act.checkWrite()) return@main | ||||||
|                         val data = currentLinks ?: return@main |  | ||||||
|                         val subs = currentSubs |  | ||||||
| 
 |  | ||||||
|                         val outputDir = act.cacheDir |  | ||||||
|                         val outputFile = withContext(Dispatchers.IO) { |  | ||||||
|                             File.createTempFile("mirrorlist", ".m3u8", outputDir) |  | ||||||
|                         } |  | ||||||
|                         var text = "#EXTM3U" |  | ||||||
|                         if (subs != null) { |  | ||||||
|                             for (sub in subs.values) { |  | ||||||
|                                 text += "\n#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"${sub.lang}\",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE=\"${sub.lang}\",URI=\"${sub.url}\"" |  | ||||||
|                             } |                             } | ||||||
|  |                             val data = currentLinks ?: return@main | ||||||
|  |                             val subs = currentSubs | ||||||
|  | 
 | ||||||
|  |                             val outputDir = act.cacheDir | ||||||
|  |                             val outputFile = withContext(Dispatchers.IO) { | ||||||
|  |                                 File.createTempFile("mirrorlist", ".m3u8", outputDir) | ||||||
|  |                             } | ||||||
|  |                             var text = "#EXTM3U" | ||||||
|  |                             if (subs != null) { | ||||||
|  |                                 for (sub in subs.values) { | ||||||
|  |                                     text += "\n#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"${sub.lang}\",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE=\"${sub.lang}\",URI=\"${sub.url}\"" | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                             for (link in data.sortedBy { -it.quality }) { | ||||||
|  |                                 text += "\n#EXTINF:, ${link.name}\n${link.url}" | ||||||
|  |                             } | ||||||
|  |                             outputFile.writeText(text) | ||||||
|  | 
 | ||||||
|  |                             val vlcIntent = Intent(VLC_INTENT_ACTION_RESULT) | ||||||
|  | 
 | ||||||
|  |                             vlcIntent.setPackage(VLC_PACKAGE) | ||||||
|  |                             vlcIntent.addFlags(FLAG_GRANT_PERSISTABLE_URI_PERMISSION) | ||||||
|  |                             vlcIntent.addFlags(FLAG_GRANT_PREFIX_URI_PERMISSION) | ||||||
|  |                             vlcIntent.addFlags(FLAG_GRANT_READ_URI_PERMISSION) | ||||||
|  |                             vlcIntent.addFlags(FLAG_GRANT_WRITE_URI_PERMISSION) | ||||||
|  | 
 | ||||||
|  |                             vlcIntent.setDataAndType( | ||||||
|  |                                 FileProvider.getUriForFile( | ||||||
|  |                                     act, | ||||||
|  |                                     act.applicationContext.packageName + ".provider", | ||||||
|  |                                     outputFile | ||||||
|  |                                 ), "video/*" | ||||||
|  |                             ) | ||||||
|  | 
 | ||||||
|  |                             val startId = VLC_FROM_PROGRESS | ||||||
|  | 
 | ||||||
|  |                             var position = startId | ||||||
|  |                             if (startId == VLC_FROM_START) { | ||||||
|  |                                 position = 1 | ||||||
|  |                             } else if (startId == VLC_FROM_PROGRESS) { | ||||||
|  |                                 position = 0 | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             vlcIntent.putExtra("position", position) | ||||||
|  | 
 | ||||||
|  |                             vlcIntent.component = VLC_COMPONENT | ||||||
|  |                             act.setKey(VLC_LAST_ID_KEY, episodeClick.data.id) | ||||||
|  |                             act.startActivityForResult(vlcIntent, VLC_REQUEST_CODE) | ||||||
|  |                         } catch (e: Exception) { | ||||||
|  |                             logError(e) | ||||||
|  |                             showToast(act, e.toString(), Toast.LENGTH_LONG) | ||||||
|                         } |                         } | ||||||
|                         for (link in data.sortedBy { -it.quality }) { |  | ||||||
|                             text += "\n#EXTINF:, ${link.name}\n${link.url}" |  | ||||||
|                         } |  | ||||||
|                         outputFile.writeText(text) |  | ||||||
| 
 |  | ||||||
|                         val vlcIntent = Intent(VLC_INTENT_ACTION_RESULT) |  | ||||||
| 
 |  | ||||||
|                         vlcIntent.setPackage(VLC_PACKAGE) |  | ||||||
|                         vlcIntent.addFlags(FLAG_GRANT_PERSISTABLE_URI_PERMISSION) |  | ||||||
|                         vlcIntent.addFlags(FLAG_GRANT_PREFIX_URI_PERMISSION) |  | ||||||
|                         vlcIntent.addFlags(FLAG_GRANT_READ_URI_PERMISSION) |  | ||||||
|                         vlcIntent.addFlags(FLAG_GRANT_WRITE_URI_PERMISSION) |  | ||||||
| 
 |  | ||||||
|                         vlcIntent.setDataAndType( |  | ||||||
|                             FileProvider.getUriForFile( |  | ||||||
|                                 act, |  | ||||||
|                                 act.applicationContext.packageName + ".provider", |  | ||||||
|                                 outputFile |  | ||||||
|                             ), "video/*" |  | ||||||
|                         ) |  | ||||||
| 
 |  | ||||||
|                         val startId = VLC_FROM_PROGRESS |  | ||||||
| 
 |  | ||||||
|                         var position = startId |  | ||||||
|                         if (startId == VLC_FROM_START) { |  | ||||||
|                             position = 1 |  | ||||||
|                         } else if (startId == VLC_FROM_PROGRESS) { |  | ||||||
|                             position = 0 |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                         vlcIntent.putExtra("position", position) |  | ||||||
| 
 |  | ||||||
|                         vlcIntent.component = VLC_COMPONENT |  | ||||||
|                         act.setKey(VLC_LAST_ID_KEY, episodeClick.data.id) |  | ||||||
|                         act.startActivityForResult(vlcIntent, VLC_REQUEST_CODE) |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | @ -786,7 +797,7 @@ class ResultFragment : Fragment() { | ||||||
|             result_bookmark_button?.text = getString(watchType.stringRes) |             result_bookmark_button?.text = getString(watchType.stringRes) | ||||||
|             result_bookmark_fab?.text = getString(watchType.stringRes) |             result_bookmark_fab?.text = getString(watchType.stringRes) | ||||||
| 
 | 
 | ||||||
|             if(watchType == WatchType.NONE) { |             if (watchType == WatchType.NONE) { | ||||||
|                 result_bookmark_fab?.context?.colorFromAttribute(R.attr.white) |                 result_bookmark_fab?.context?.colorFromAttribute(R.attr.white) | ||||||
|             } else { |             } else { | ||||||
|                 result_bookmark_fab?.context?.colorFromAttribute(R.attr.colorPrimary) |                 result_bookmark_fab?.context?.colorFromAttribute(R.attr.colorPrimary) | ||||||
|  | @ -797,7 +808,7 @@ class ResultFragment : Fragment() { | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             result_bookmark_fab?.setOnClickListener { fab -> |             result_bookmark_fab?.setOnClickListener { fab -> | ||||||
|                 fab.context.showBottomDialog( |                 activity?.showBottomDialog( | ||||||
|                     WatchType.values().map { fab.context.getString(it.stringRes) }.toList(), |                     WatchType.values().map { fab.context.getString(it.stringRes) }.toList(), | ||||||
|                     watchType.ordinal, |                     watchType.ordinal, | ||||||
|                     fab.context.getString(R.string.action_add_to_bookmarks), |                     fab.context.getString(R.string.action_add_to_bookmarks), | ||||||
|  |  | ||||||
|  | @ -449,6 +449,7 @@ class ResultViewModel : ViewModel() { | ||||||
|         data: String, |         data: String, | ||||||
|         isCasting: Boolean, |         isCasting: Boolean, | ||||||
|     ): Resource<EpisodeData> { |     ): Resource<EpisodeData> { | ||||||
|  |         println("LOAD EPISODE FFS") | ||||||
|         if (_allEpisodes.value?.contains(id) == true) { |         if (_allEpisodes.value?.contains(id) == true) { | ||||||
|             _allEpisodes.value?.remove(id) |             _allEpisodes.value?.remove(id) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSet | ||||||
| import com.lagradost.cloudstream3.utils.DataStore.getKey | import com.lagradost.cloudstream3.utils.DataStore.getKey | ||||||
| import com.lagradost.cloudstream3.utils.DataStore.setKey | import com.lagradost.cloudstream3.utils.DataStore.setKey | ||||||
| import com.lagradost.cloudstream3.utils.SEARCH_PROVIDER_TOGGLE | import com.lagradost.cloudstream3.utils.SEARCH_PROVIDER_TOGGLE | ||||||
|  | import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact | import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | ||||||
|  | @ -255,11 +256,11 @@ class SearchFragment : Fragment() { | ||||||
|                     providersActive = activeApis |                     providersActive = activeApis | ||||||
|                     typesActive = activeTypes |                     typesActive = activeTypes | ||||||
| 
 | 
 | ||||||
|                     dialog.dismiss() |                     dialog.dismissSafe(activity) | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 cancelButton.setOnClickListener { |                 cancelButton.setOnClickListener { | ||||||
|                     dialog.dismiss() |                     dialog.dismissSafe(activity) | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 //listView.setSelection(selectedIndex) |                 //listView.setSelection(selectedIndex) | ||||||
|  |  | ||||||
|  | @ -45,6 +45,7 @@ import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog | ||||||
| import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog | import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog | ||||||
| import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog | import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog | ||||||
| import com.lagradost.cloudstream3.utils.SubtitleHelper | import com.lagradost.cloudstream3.utils.SubtitleHelper | ||||||
|  | import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.setImage | import com.lagradost.cloudstream3.utils.UIHelper.setImage | ||||||
| import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath | import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath | ||||||
|  | @ -147,7 +148,7 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|         } |         } | ||||||
|         api.accountIndex = ogIndex |         api.accountIndex = ogIndex | ||||||
|         val adapter = AccountAdapter(items, R.layout.account_single) { |         val adapter = AccountAdapter(items, R.layout.account_single) { | ||||||
|             dialog?.dismiss() |             dialog?.dismissSafe(activity) | ||||||
|             api.changeAccount(it.view.context, it.card.accountIndex) |             api.changeAccount(it.view.context, it.card.accountIndex) | ||||||
|         } |         } | ||||||
|         val list = dialog.findViewById<RecyclerView>(R.id.account_list) |         val list = dialog.findViewById<RecyclerView>(R.id.account_list) | ||||||
|  | @ -163,14 +164,14 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|         dialog.findViewById<TextView>(R.id.account_logout)?.setOnClickListener { |         dialog.findViewById<TextView>(R.id.account_logout)?.setOnClickListener { | ||||||
|             it.context?.let { ctx -> |             it.context?.let { ctx -> | ||||||
|                 api.logOut(ctx) |                 api.logOut(ctx) | ||||||
|                 dialog.dismiss() |                 dialog.dismissSafe(activity) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         dialog.findViewById<TextView>(R.id.account_name)?.text = info.name ?: context.getString(R.string.no_data) |         dialog.findViewById<TextView>(R.id.account_name)?.text = info.name ?: context.getString(R.string.no_data) | ||||||
|         dialog.findViewById<TextView>(R.id.account_site)?.text = api.name |         dialog.findViewById<TextView>(R.id.account_site)?.text = api.name | ||||||
|         dialog.findViewById<TextView>(R.id.account_switch_account)?.setOnClickListener { |         dialog.findViewById<TextView>(R.id.account_switch_account)?.setOnClickListener { | ||||||
|             dialog.dismiss() |             dialog.dismissSafe(activity) | ||||||
|             showAccountSwitch(it.context, api) |             showAccountSwitch(it.context, api) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -178,6 +179,7 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { |     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { | ||||||
|         hideKeyboard() |         hideKeyboard() | ||||||
|         setPreferencesFromResource(R.xml.settings, rootKey) |         setPreferencesFromResource(R.xml.settings, rootKey) | ||||||
|  | 
 | ||||||
|         val updatePreference = findPreference<Preference>(getString(R.string.manual_check_update_key))!! |         val updatePreference = findPreference<Preference>(getString(R.string.manual_check_update_key))!! | ||||||
|         val localePreference = findPreference<Preference>(getString(R.string.locale_key))!! |         val localePreference = findPreference<Preference>(getString(R.string.locale_key))!! | ||||||
|         val benenePreference = findPreference<Preference>(getString(R.string.benene_count))!! |         val benenePreference = findPreference<Preference>(getString(R.string.benene_count))!! | ||||||
|  | @ -191,6 +193,12 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|         val colorPrimaryPreference = findPreference<Preference>(getString(R.string.primary_color_key))!! |         val colorPrimaryPreference = findPreference<Preference>(getString(R.string.primary_color_key))!! | ||||||
|         val preferedMediaTypePreference = findPreference<Preference>(getString(R.string.prefer_media_type_key))!! |         val preferedMediaTypePreference = findPreference<Preference>(getString(R.string.prefer_media_type_key))!! | ||||||
|         val appThemePreference = findPreference<Preference>(getString(R.string.app_theme_key))!! |         val appThemePreference = findPreference<Preference>(getString(R.string.app_theme_key))!! | ||||||
|  |         val subPreference = findPreference<Preference>(getString(R.string.subtitle_settings_key))!! | ||||||
|  | 
 | ||||||
|  |         subPreference.setOnPreferenceClickListener { | ||||||
|  |             SubtitlesFragment.push(activity, false) | ||||||
|  |             return@setOnPreferenceClickListener true | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         val syncApis = listOf(Pair(R.string.mal_key, malApi), Pair(R.string.anilist_key, aniListApi)) |         val syncApis = listOf(Pair(R.string.mal_key, malApi), Pair(R.string.anilist_key, aniListApi)) | ||||||
|         for (sync in syncApis) { |         for (sync in syncApis) { | ||||||
|  | @ -233,7 +241,7 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|                     currentList.add(dublist.indexOf(i)) |                     currentList.add(dublist.indexOf(i)) | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 context?.showMultiDialog( |                 activity?.showMultiDialog( | ||||||
|                     names, |                     names, | ||||||
|                     currentList, |                     currentList, | ||||||
|                     getString(R.string.display_subbed_dubbed_settings), |                     getString(R.string.display_subbed_dubbed_settings), | ||||||
|  | @ -276,7 +284,7 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|                     Pair(it, fullName) |                     Pair(it, fullName) | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 context?.showMultiDialog( |                 activity?.showMultiDialog( | ||||||
|                     names.map { it.second }, |                     names.map { it.second }, | ||||||
|                     currentList, |                     currentList, | ||||||
|                     getString(R.string.provider_lang_settings), |                     getString(R.string.provider_lang_settings), | ||||||
|  | @ -299,12 +307,16 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|             // DOES NOT WORK ON SCOPED STORAGE. |             // DOES NOT WORK ON SCOPED STORAGE. | ||||||
|             val secondaryDir = if (isScopedStorage) null else Environment.getExternalStorageDirectory().absolutePath + |             val secondaryDir = if (isScopedStorage) null else Environment.getExternalStorageDirectory().absolutePath + | ||||||
|                     File.separator + resources.getString(R.string.app_name_download_path) |                     File.separator + resources.getString(R.string.app_name_download_path) | ||||||
|  |             val first = listOf(defaultDir, secondaryDir) | ||||||
|  |             return (try { | ||||||
|  |                 val currentDir = context?.getBasePath()?.let { it.first?.filePath ?: it.second } | ||||||
| 
 | 
 | ||||||
|             val currentDir = context?.getBasePath()?.let { it.first?.filePath ?: it.second } |                 (first + | ||||||
| 
 |                         requireContext().getExternalFilesDirs("").mapNotNull { it.path } + | ||||||
|             return (listOf(defaultDir, secondaryDir) + |                         currentDir) | ||||||
|                     requireContext().getExternalFilesDirs("").mapNotNull { it.path } + |             } catch (e: Exception) { | ||||||
|                     currentDir).filterNotNull().distinct() |                 first | ||||||
|  |             }).filterNotNull().distinct() | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         downloadPathPreference.setOnPreferenceClickListener { |         downloadPathPreference.setOnPreferenceClickListener { | ||||||
|  | @ -314,7 +326,7 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|             val currentDir = |             val currentDir = | ||||||
|                 settingsManager.getString(getString(R.string.download_path_pref), null) ?: getDownloadDir().toString() |                 settingsManager.getString(getString(R.string.download_path_pref), null) ?: getDownloadDir().toString() | ||||||
| 
 | 
 | ||||||
|             context?.showBottomDialog( |             activity?.showBottomDialog( | ||||||
|                 dirs + listOf("Custom"), |                 dirs + listOf("Custom"), | ||||||
|                 dirs.indexOf(currentDir), |                 dirs.indexOf(currentDir), | ||||||
|                 getString(R.string.download_path_pref), |                 getString(R.string.download_path_pref), | ||||||
|  | @ -342,7 +354,7 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|             val currentPrefMedia = |             val currentPrefMedia = | ||||||
|                 settingsManager.getInt(getString(R.string.preferred_media_settings), 0) |                 settingsManager.getInt(getString(R.string.preferred_media_settings), 0) | ||||||
| 
 | 
 | ||||||
|             context?.showBottomDialog( |             activity?.showBottomDialog( | ||||||
|                 prefNames.toList(), |                 prefNames.toList(), | ||||||
|                 prefValues.indexOf(currentPrefMedia), |                 prefValues.indexOf(currentPrefMedia), | ||||||
|                 getString(R.string.preferred_media_settings), |                 getString(R.string.preferred_media_settings), | ||||||
|  | @ -352,7 +364,11 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|                     .putInt(getString(R.string.preferred_media_settings), prefValues[it]) |                     .putInt(getString(R.string.preferred_media_settings), prefValues[it]) | ||||||
|                     .apply() |                     .apply() | ||||||
|                 val apilist = AppUtils.filterProviderByPreferredMedia(apis, prefValues[it]) |                 val apilist = AppUtils.filterProviderByPreferredMedia(apis, prefValues[it]) | ||||||
|                 val apiRandom = if (apilist.size > 0) { apilist.random().name } else { "" } |                 val apiRandom = if (apilist.size > 0) { | ||||||
|  |                     apilist.random().name | ||||||
|  |                 } else { | ||||||
|  |                     "" | ||||||
|  |                 } | ||||||
|                 context?.setKey(HOMEPAGE_API, apiRandom) |                 context?.setKey(HOMEPAGE_API, apiRandom) | ||||||
|                 (context ?: AcraApplication.context)?.let { ctx -> app.initClient(ctx) } |                 (context ?: AcraApplication.context)?.let { ctx -> app.initClient(ctx) } | ||||||
|             } |             } | ||||||
|  | @ -366,7 +382,8 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
| 
 | 
 | ||||||
|             val currentLayout = |             val currentLayout = | ||||||
|                 settingsManager.getInt(getString(R.string.app_layout_key), -1) |                 settingsManager.getInt(getString(R.string.app_layout_key), -1) | ||||||
|             context?.showBottomDialog( | 
 | ||||||
|  |             activity?.showBottomDialog( | ||||||
|                 prefNames.toList(), |                 prefNames.toList(), | ||||||
|                 prefValues.indexOf(currentLayout), |                 prefValues.indexOf(currentLayout), | ||||||
|                 getString(R.string.app_layout), |                 getString(R.string.app_layout), | ||||||
|  | @ -390,7 +407,8 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
| 
 | 
 | ||||||
|             val currentLayout = |             val currentLayout = | ||||||
|                 settingsManager.getString(getString(R.string.primary_color_key), prefValues.first()) |                 settingsManager.getString(getString(R.string.primary_color_key), prefValues.first()) | ||||||
|             context?.showBottomDialog( | 
 | ||||||
|  |             activity?.showBottomDialog( | ||||||
|                 prefNames.toList(), |                 prefNames.toList(), | ||||||
|                 prefValues.indexOf(currentLayout), |                 prefValues.indexOf(currentLayout), | ||||||
|                 getString(R.string.primary_color_settings), |                 getString(R.string.primary_color_settings), | ||||||
|  | @ -414,7 +432,8 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
| 
 | 
 | ||||||
|             val currentLayout = |             val currentLayout = | ||||||
|                 settingsManager.getString(getString(R.string.app_theme_key), prefValues.first()) |                 settingsManager.getString(getString(R.string.app_theme_key), prefValues.first()) | ||||||
|             context?.showBottomDialog( | 
 | ||||||
|  |             activity?.showBottomDialog( | ||||||
|                 prefNames.toList(), |                 prefNames.toList(), | ||||||
|                 prefValues.indexOf(currentLayout), |                 prefValues.indexOf(currentLayout), | ||||||
|                 getString(R.string.app_theme_settings), |                 getString(R.string.app_theme_settings), | ||||||
|  | @ -441,7 +460,8 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|                     getString(R.string.watch_quality_pref), |                     getString(R.string.watch_quality_pref), | ||||||
|                     Qualities.values().last().value |                     Qualities.values().last().value | ||||||
|                 ) |                 ) | ||||||
|             context?.showBottomDialog( | 
 | ||||||
|  |             activity?.showBottomDialog( | ||||||
|                 prefNames.toList(), |                 prefNames.toList(), | ||||||
|                 prefValues.indexOf(currentQuality), |                 prefValues.indexOf(currentQuality), | ||||||
|                 getString(R.string.watch_quality_pref), |                 getString(R.string.watch_quality_pref), | ||||||
|  | @ -460,7 +480,8 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
| 
 | 
 | ||||||
|             val currentDns = |             val currentDns = | ||||||
|                 settingsManager.getInt(getString(R.string.dns_pref), 0) |                 settingsManager.getInt(getString(R.string.dns_pref), 0) | ||||||
|             context?.showBottomDialog( | 
 | ||||||
|  |             activity?.showBottomDialog( | ||||||
|                 prefNames.toList(), |                 prefNames.toList(), | ||||||
|                 prefValues.indexOf(currentDns), |                 prefValues.indexOf(currentDns), | ||||||
|                 getString(R.string.dns_pref), |                 getString(R.string.dns_pref), | ||||||
|  | @ -481,6 +502,7 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|                 if (beneneCount <= 0) getString(R.string.benene_count_text_none) else getString(R.string.benene_count_text).format( |                 if (beneneCount <= 0) getString(R.string.benene_count_text_none) else getString(R.string.benene_count_text).format( | ||||||
|                     beneneCount |                     beneneCount | ||||||
|                 ) |                 ) | ||||||
|  | 
 | ||||||
|             benenePreference.setOnPreferenceClickListener { |             benenePreference.setOnPreferenceClickListener { | ||||||
|                 try { |                 try { | ||||||
|                     beneneCount++ |                     beneneCount++ | ||||||
|  | @ -516,7 +538,8 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|             val languageCodes = tempLangs.map { it.third } |             val languageCodes = tempLangs.map { it.third } | ||||||
|             val languageNames = tempLangs.map { "${it.first}  ${it.second}" } |             val languageNames = tempLangs.map { "${it.first}  ${it.second}" } | ||||||
|             val index = languageCodes.indexOf(current) |             val index = languageCodes.indexOf(current) | ||||||
|             pref?.context?.showDialog( | 
 | ||||||
|  |             activity?.showDialog( | ||||||
|                 languageNames, index, getString(R.string.app_language), true, { } |                 languageNames, index, getString(R.string.app_language), true, { } | ||||||
|             ) { languageIndex -> |             ) { languageIndex -> | ||||||
|                 try { |                 try { | ||||||
|  | @ -540,13 +563,4 @@ class SettingsFragment : PreferenceFragmentCompat() { | ||||||
|         val conf = res.configuration |         val conf = res.configuration | ||||||
|         return conf?.locale?.language ?: "en" |         return conf?.locale?.language ?: "en" | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     override fun onPreferenceTreeClick(preference: Preference?): Boolean { |  | ||||||
|         if (preference != null) { |  | ||||||
|             if (preference.key == getString(R.string.subtitle_settings_key)) { |  | ||||||
|                 SubtitlesFragment.push(activity, false) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return super.onPreferenceTreeClick(preference) |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -232,7 +232,7 @@ class SubtitlesFragment : Fragment() { | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|             //showBottomDialog |             //showBottomDialog | ||||||
|             textView.context.showDialog( |             activity?.showDialog( | ||||||
|                 elevationTypes.map { it.second }, |                 elevationTypes.map { it.second }, | ||||||
|                 elevationTypes.map { it.first }.indexOf(state.elevation), |                 elevationTypes.map { it.first }.indexOf(state.elevation), | ||||||
|                 (textView as TextView).text.toString(), |                 (textView as TextView).text.toString(), | ||||||
|  | @ -263,7 +263,7 @@ class SubtitlesFragment : Fragment() { | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|             //showBottomDialog |             //showBottomDialog | ||||||
|             textView.context.showDialog( |             activity?.showDialog( | ||||||
|                 edgeTypes.map { it.second }, |                 edgeTypes.map { it.second }, | ||||||
|                 edgeTypes.map { it.first }.indexOf(state.edgeType), |                 edgeTypes.map { it.first }.indexOf(state.edgeType), | ||||||
|                 (textView as TextView).text.toString(), |                 (textView as TextView).text.toString(), | ||||||
|  | @ -314,7 +314,7 @@ class SubtitlesFragment : Fragment() { | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|             //showBottomDialog |             //showBottomDialog | ||||||
|             textView.context.showDialog( |             activity?.showDialog( | ||||||
|                 fontSizes.map { it.second }, |                 fontSizes.map { it.second }, | ||||||
|                 fontSizes.map { it.first }.indexOf(state.fixedTextSize), |                 fontSizes.map { it.first }.indexOf(state.fixedTextSize), | ||||||
|                 (textView as TextView).text.toString(), |                 (textView as TextView).text.toString(), | ||||||
|  | @ -353,7 +353,7 @@ class SubtitlesFragment : Fragment() { | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|             //showBottomDialog |             //showBottomDialog | ||||||
|             textView.context.showDialog( |             activity?.showDialog( | ||||||
|                 fontTypes.map { it.second }, |                 fontTypes.map { it.second }, | ||||||
|                 fontTypes.map { it.first }.indexOf(state.typeface), |                 fontTypes.map { it.first }.indexOf(state.typeface), | ||||||
|                 (textView as TextView).text.toString(), |                 (textView as TextView).text.toString(), | ||||||
|  | @ -379,7 +379,7 @@ class SubtitlesFragment : Fragment() { | ||||||
|             langMap.addAll(SubtitleHelper.languages) |             langMap.addAll(SubtitleHelper.languages) | ||||||
| 
 | 
 | ||||||
|             val lang639_1 = langMap.map { it.ISO_639_1 } |             val lang639_1 = langMap.map { it.ISO_639_1 } | ||||||
|             textView.context.showDialog( |             activity?.showDialog( | ||||||
|                 langMap.map { it.languageName }, |                 langMap.map { it.languageName }, | ||||||
|                 lang639_1.indexOf(textView.context.getAutoSelectLanguageISO639_1()), |                 lang639_1.indexOf(textView.context.getAutoSelectLanguageISO639_1()), | ||||||
|                 (textView as TextView).text.toString(), |                 (textView as TextView).text.toString(), | ||||||
|  | @ -402,7 +402,7 @@ class SubtitlesFragment : Fragment() { | ||||||
|             val keys = textView.context.getDownloadSubsLanguageISO639_1() |             val keys = textView.context.getDownloadSubsLanguageISO639_1() | ||||||
|             val keyMap = keys.map { lang639_1.indexOf(it) }.filter { it >= 0 } |             val keyMap = keys.map { lang639_1.indexOf(it) }.filter { it >= 0 } | ||||||
| 
 | 
 | ||||||
|             textView.context.showMultiDialog( |             activity?.showMultiDialog( | ||||||
|                 langMap.map { it.languageName }, |                 langMap.map { it.languageName }, | ||||||
|                 keyMap, |                 keyMap, | ||||||
|                 (textView as TextView).text.toString(), |                 (textView as TextView).text.toString(), | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| package com.lagradost.cloudstream3.utils | package com.lagradost.cloudstream3.utils | ||||||
| 
 | 
 | ||||||
|  | import android.app.Activity | ||||||
| import android.app.Dialog | import android.app.Dialog | ||||||
| import android.content.Context |  | ||||||
| import android.widget.* | import android.widget.* | ||||||
| import androidx.appcompat.app.AlertDialog | import androidx.appcompat.app.AlertDialog | ||||||
| import androidx.core.view.isVisible | import androidx.core.view.isVisible | ||||||
|  | @ -10,9 +10,10 @@ import androidx.core.view.marginRight | ||||||
| import androidx.core.view.marginTop | import androidx.core.view.marginTop | ||||||
| import com.google.android.material.bottomsheet.BottomSheetDialog | import com.google.android.material.bottomsheet.BottomSheetDialog | ||||||
| import com.lagradost.cloudstream3.R | import com.lagradost.cloudstream3.R | ||||||
|  | import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe | ||||||
| 
 | 
 | ||||||
| object SingleSelectionHelper { | object SingleSelectionHelper { | ||||||
|     fun Context.showDialog( |     fun Activity.showDialog( | ||||||
|         dialog: Dialog, |         dialog: Dialog, | ||||||
|         items: List<String>, |         items: List<String>, | ||||||
|         selectedIndex: List<Int>, |         selectedIndex: List<Int>, | ||||||
|  | @ -70,7 +71,7 @@ object SingleSelectionHelper { | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 callback.invoke(listOf(which)) |                 callback.invoke(listOf(which)) | ||||||
|                 dialog.dismiss() |                 dialog.dismissSafe(this) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (realShowApply) { |         if (realShowApply) { | ||||||
|  | @ -81,15 +82,15 @@ object SingleSelectionHelper { | ||||||
|                         list.add(index) |                         list.add(index) | ||||||
|                 } |                 } | ||||||
|                 callback.invoke(list) |                 callback.invoke(list) | ||||||
|                 dialog.dismiss() |                 dialog.dismissSafe(this) | ||||||
|             } |             } | ||||||
|             cancelButton.setOnClickListener { |             cancelButton.setOnClickListener { | ||||||
|                 dialog.dismiss() |                 dialog.dismissSafe(this) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun Context.showMultiDialog( |     fun Activity.showMultiDialog( | ||||||
|         items: List<String>, |         items: List<String>, | ||||||
|         selectedIndex: List<Int>, |         selectedIndex: List<Int>, | ||||||
|         name: String, |         name: String, | ||||||
|  | @ -104,7 +105,7 @@ object SingleSelectionHelper { | ||||||
|         showDialog(dialog, items, selectedIndex, name, true, true, callback, dismissCallback) |         showDialog(dialog, items, selectedIndex, name, true, true, callback, dismissCallback) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun Context.showDialog( |     fun Activity.showDialog( | ||||||
|         items: List<String>, |         items: List<String>, | ||||||
|         selectedIndex: Int, |         selectedIndex: Int, | ||||||
|         name: String, |         name: String, | ||||||
|  | @ -130,7 +131,7 @@ object SingleSelectionHelper { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** Only for a low amount of items */ |     /** Only for a low amount of items */ | ||||||
|     fun Context.showBottomDialog( |     fun Activity.showBottomDialog( | ||||||
|         items: List<String>, |         items: List<String>, | ||||||
|         selectedIndex: Int, |         selectedIndex: Int, | ||||||
|         name: String, |         name: String, | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ import android.Manifest | ||||||
| import android.annotation.SuppressLint | import android.annotation.SuppressLint | ||||||
| import android.app.Activity | import android.app.Activity | ||||||
| import android.app.AppOpsManager | import android.app.AppOpsManager | ||||||
|  | import android.app.Dialog | ||||||
| import android.content.Context | import android.content.Context | ||||||
| import android.content.pm.PackageManager | import android.content.pm.PackageManager | ||||||
| import android.content.res.Resources | import android.content.res.Resources | ||||||
|  | @ -293,8 +294,13 @@ object UIHelper { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun Context.shouldShowPIPMode(isInPlayer: Boolean): Boolean { |     fun Context.shouldShowPIPMode(isInPlayer: Boolean): Boolean { | ||||||
|         val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) |         return try { | ||||||
|         return settingsManager?.getBoolean("pip_enabled", true) ?: true && isInPlayer |             val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) | ||||||
|  |             settingsManager?.getBoolean(getString(R.string.pip_enabled_key), true) ?: true && isInPlayer | ||||||
|  |         } catch (e : Exception) { | ||||||
|  |             logError(e) | ||||||
|  |             false | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @RequiresApi(Build.VERSION_CODES.O) |     @RequiresApi(Build.VERSION_CODES.O) | ||||||
|  | @ -319,6 +325,12 @@ object UIHelper { | ||||||
|         inputMethodManager?.showSoftInput(view, 0) |         inputMethodManager?.showSoftInput(view, 0) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     fun Dialog?.dismissSafe(activity: Activity?) { | ||||||
|  |         if (this?.isShowing == true && activity?.isFinishing == false) { | ||||||
|  |             this.dismiss() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /**id, stringRes */ |     /**id, stringRes */ | ||||||
|     @SuppressLint("RestrictedApi") |     @SuppressLint("RestrictedApi") | ||||||
|     fun View.popupMenuNoIcons( |     fun View.popupMenuNoIcons( | ||||||
|  |  | ||||||
|  | @ -1,63 +0,0 @@ | ||||||
| <?xml version="1.0" encoding="utf-8"?> |  | ||||||
| <FrameLayout |  | ||||||
|         xmlns:android="http://schemas.android.com/apk/res/android" |  | ||||||
|         xmlns:app="http://schemas.android.com/apk/res-auto" |  | ||||||
|         xmlns:tools="http://schemas.android.com/tools" |  | ||||||
|         android:id="@+id/homeRoot" |  | ||||||
|         android:layout_width="match_parent" |  | ||||||
|         android:layout_height="match_parent" |  | ||||||
|         android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|keyboard|navigation" |  | ||||||
|         android:paddingTop="0dp"> |  | ||||||
|     <androidx.constraintlayout.widget.ConstraintLayout |  | ||||||
|             android:layout_height="match_parent" |  | ||||||
|             android:layout_width="match_parent"> |  | ||||||
|         <com.google.android.material.navigationrail.NavigationRailView |  | ||||||
|                 android:layout_width="62dp" |  | ||||||
|                 android:layout_height="match_parent" |  | ||||||
|                 android:id="@+id/nav_rail_view" |  | ||||||
|                 android:background="?attr/primaryGrayBackground" |  | ||||||
|                 app:itemTextColor="@color/item_select_color" |  | ||||||
|                 app:itemIconTint="@color/item_select_color" |  | ||||||
|                 app:menuGravity="center" |  | ||||||
|                 app:layout_constraintStart_toStartOf="parent" |  | ||||||
|                 app:layout_constraintTop_toTopOf="parent" |  | ||||||
|                 app:labelVisibilityMode="unlabeled" |  | ||||||
|                 app:menu="@menu/bottom_nav_menu"> |  | ||||||
| 
 |  | ||||||
|         </com.google.android.material.navigationrail.NavigationRailView> |  | ||||||
| 
 |  | ||||||
|         <fragment |  | ||||||
|                 android:id="@+id/nav_host_fragment" |  | ||||||
|                 android:name="androidx.navigation.fragment.NavHostFragment" |  | ||||||
|                 android:layout_width="0dp" |  | ||||||
|                 android:layout_height="0dp" |  | ||||||
|                 app:defaultNavHost="true" |  | ||||||
|                 app:layout_constraintTop_toTopOf="parent" |  | ||||||
|                 app:layout_constraintLeft_toRightOf="parent" |  | ||||||
|                 app:layout_constraintBottom_toTopOf="@id/cast_mini_controller_holder" |  | ||||||
|                 app:navGraph="@navigation/mobile_navigation" |  | ||||||
|                 app:layout_constraintStart_toEndOf="@id/nav_rail_view" |  | ||||||
|                 app:layout_constraintEnd_toEndOf="parent"/> |  | ||||||
|         <LinearLayout |  | ||||||
|                 app:layout_constraintStart_toEndOf="@+id/nav_rail_view" |  | ||||||
|                 app:layout_constraintEnd_toEndOf="parent" |  | ||||||
|                 app:layout_constraintBottom_toBottomOf="parent" |  | ||||||
|                 tools:layout_height="100dp" |  | ||||||
|                 android:layout_width="0dp" |  | ||||||
|                 android:layout_height="wrap_content" |  | ||||||
|                 android:id="@+id/cast_mini_controller_holder" |  | ||||||
|         > |  | ||||||
|             <!--com.google.android.gms.cast.framework.media.widget.MiniControllerFragment--> |  | ||||||
|             <fragment |  | ||||||
|                     app:customCastBackgroundColor="?attr/primaryGrayBackground" |  | ||||||
|                     app:castControlButtons="@array/cast_mini_controller_control_buttons" |  | ||||||
|                     android:id="@+id/cast_mini_controller" |  | ||||||
|                     android:layout_width="match_parent" |  | ||||||
|                     android:layout_height="wrap_content" |  | ||||||
|                     android:visibility="gone" |  | ||||||
|                     class="com.lagradost.cloudstream3.ui.MyMiniControllerFragment" |  | ||||||
|                     tools:ignore="FragmentTagUsage"> |  | ||||||
|             </fragment> |  | ||||||
|         </LinearLayout> |  | ||||||
|     </androidx.constraintlayout.widget.ConstraintLayout> |  | ||||||
| </FrameLayout> |  | ||||||
|  | @ -11,6 +11,22 @@ | ||||||
|     <androidx.constraintlayout.widget.ConstraintLayout |     <androidx.constraintlayout.widget.ConstraintLayout | ||||||
|             android:layout_height="match_parent" |             android:layout_height="match_parent" | ||||||
|             android:layout_width="match_parent"> |             android:layout_width="match_parent"> | ||||||
|  |         <com.google.android.material.navigationrail.NavigationRailView | ||||||
|  |                 android:layout_width="62dp" | ||||||
|  |                 android:layout_height="match_parent" | ||||||
|  |                 android:id="@+id/nav_rail_view" | ||||||
|  |                 android:background="?attr/primaryGrayBackground" | ||||||
|  |                 app:itemTextColor="@color/item_select_color" | ||||||
|  |                 app:itemIconTint="@color/item_select_color" | ||||||
|  |                 app:menuGravity="center" | ||||||
|  |                 app:layout_constraintStart_toStartOf="parent" | ||||||
|  |                 app:layout_constraintTop_toTopOf="parent" | ||||||
|  |                 app:layout_constraintBottom_toBottomOf="parent" | ||||||
|  |                 app:labelVisibilityMode="unlabeled" | ||||||
|  |                 app:menu="@menu/bottom_nav_menu"> | ||||||
|  | 
 | ||||||
|  |         </com.google.android.material.navigationrail.NavigationRailView> | ||||||
|  | 
 | ||||||
|         <com.google.android.material.bottomnavigation.BottomNavigationView |         <com.google.android.material.bottomnavigation.BottomNavigationView | ||||||
|                 android:id="@+id/nav_view" |                 android:id="@+id/nav_view" | ||||||
|                 android:layout_width="0dp" |                 android:layout_width="0dp" | ||||||
|  | @ -28,17 +44,20 @@ | ||||||
|         <fragment |         <fragment | ||||||
|                 android:id="@+id/nav_host_fragment" |                 android:id="@+id/nav_host_fragment" | ||||||
|                 android:name="androidx.navigation.fragment.NavHostFragment" |                 android:name="androidx.navigation.fragment.NavHostFragment" | ||||||
|                 android:layout_width="match_parent" |                 android:layout_width="0dp" | ||||||
|                 android:layout_height="0dp" |                 android:layout_height="0dp" | ||||||
|                 app:defaultNavHost="true" |                 app:defaultNavHost="true" | ||||||
|  |                 app:navGraph="@navigation/mobile_navigation" | ||||||
|  |                 app:layout_constraintStart_toEndOf="@+id/nav_rail_view" | ||||||
|                 app:layout_constraintBottom_toTopOf="@+id/cast_mini_controller_holder" |                 app:layout_constraintBottom_toTopOf="@+id/cast_mini_controller_holder" | ||||||
|                 app:layout_constraintTop_toTopOf="parent" |                 app:layout_constraintTop_toTopOf="parent" | ||||||
|                 app:navGraph="@navigation/mobile_navigation" |  | ||||||
|                 app:layout_constraintEnd_toEndOf="parent"/> |                 app:layout_constraintEnd_toEndOf="parent"/> | ||||||
|         <LinearLayout |         <LinearLayout | ||||||
|                 tools:layout_height="100dp" |                 tools:layout_height="100dp" | ||||||
|                 android:layout_width="match_parent" |                 android:layout_width="0dp" | ||||||
|  |                 app:layout_constraintStart_toEndOf="@+id/nav_rail_view" | ||||||
|                 android:layout_height="wrap_content" |                 android:layout_height="wrap_content" | ||||||
|  |                 app:layout_constraintEnd_toEndOf="parent" | ||||||
|                 app:layout_constraintBottom_toTopOf="@+id/nav_view" |                 app:layout_constraintBottom_toTopOf="@+id/nav_view" | ||||||
|                 android:id="@+id/cast_mini_controller_holder" |                 android:id="@+id/cast_mini_controller_holder" | ||||||
|         > |         > | ||||||
|  |  | ||||||
|  | @ -140,7 +140,7 @@ | ||||||
|     <string name="delete">Verwijderen</string> |     <string name="delete">Verwijderen</string> | ||||||
|     <string name="pause">Pauze</string> |     <string name="pause">Pauze</string> | ||||||
|     <string name="resume">Hervat</string> |     <string name="resume">Hervat</string> | ||||||
|     <string name="delete_message">Dit wordt zeker permanent verwijderd %a\Weet u het zeker?</string> |     <string name="delete_message">Dit wordt zeker permanent verwijderd %s\nWeet u het zeker?</string> | ||||||
| 
 | 
 | ||||||
|     <string name="status_ongoing">Lopend</string> |     <string name="status_ongoing">Lopend</string> | ||||||
|     <string name="status_completed">Voltooid</string> |     <string name="status_completed">Voltooid</string> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue