mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	Implementation of player settings page in Settings page redesign
- Added new files for the Fragment and xml related to the player settings page. - Implemented the player settings page per the description in https://github.com/TeamNewPipe/NewPipe/issues/9587. - These changes facilitate easier switching between current and new behaviors. - They also lay the groundwork for easier cleanup when the new design is approved and enabled by default. Video: - https://github.com/TeamNewPipe/NewPipe/assets/87667048/00385bbb-6a2f-4ce5-b6b9-6cf1cb5c5636
This commit is contained in:
		| @@ -0,0 +1,211 @@ | |||||||
|  | package org.schabi.newpipe.settings | ||||||
|  |  | ||||||
|  | import android.content.ActivityNotFoundException | ||||||
|  | import android.content.Intent | ||||||
|  | import android.content.SharedPreferences.OnSharedPreferenceChangeListener | ||||||
|  | import android.content.res.Resources.NotFoundException | ||||||
|  | import android.os.Build | ||||||
|  | import android.os.Bundle | ||||||
|  | import android.provider.Settings | ||||||
|  | import android.text.format.DateUtils | ||||||
|  | import android.widget.Toast | ||||||
|  | import androidx.preference.ListPreference | ||||||
|  | import androidx.preference.Preference | ||||||
|  | import com.google.android.material.snackbar.Snackbar | ||||||
|  | import org.schabi.newpipe.R | ||||||
|  | import org.schabi.newpipe.util.ListHelper | ||||||
|  | import org.schabi.newpipe.util.PermissionHelper | ||||||
|  | import java.util.LinkedList | ||||||
|  |  | ||||||
|  | class PlayerSettingsFragment : BasePreferenceFragment() { | ||||||
|  |     private lateinit var listener: OnSharedPreferenceChangeListener | ||||||
|  |  | ||||||
|  |     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { | ||||||
|  |         addPreferencesFromResourceRegistry() | ||||||
|  |         updateSeekOptions() | ||||||
|  |         updateResolutionOptions() | ||||||
|  |         listener = OnSharedPreferenceChangeListener { sharedPreferences, key -> | ||||||
|  |             // on M and above, if user chooses to minimise to popup player on exit and the app | ||||||
|  |             // doesn't have display over other apps permission, show a snack bar to let the user | ||||||
|  |             // give permission | ||||||
|  |             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && | ||||||
|  |                 getString(R.string.minimize_on_exit_key) == key | ||||||
|  |             ) { | ||||||
|  |                 sharedPreferences.getString(key, null) | ||||||
|  |                     ?.takeIf { | ||||||
|  |                         getString(R.string.minimize_on_exit_popup_key) == it && | ||||||
|  |                             !Settings.canDrawOverlays(context) | ||||||
|  |                     }?.let { | ||||||
|  |                         Snackbar.make( | ||||||
|  |                             listView, | ||||||
|  |                             R.string.permission_display_over_apps, | ||||||
|  |                             Snackbar.LENGTH_INDEFINITE, | ||||||
|  |                         ).setAction(R.string.settings) { | ||||||
|  |                             PermissionHelper.checkSystemAlertWindowPermission(context) | ||||||
|  |                         }.show() | ||||||
|  |                     } | ||||||
|  |             } else if (getString(R.string.use_inexact_seek_key) == key) { | ||||||
|  |                 updateSeekOptions() | ||||||
|  |             } else if (getString(R.string.show_higher_resolutions_key) == key) { | ||||||
|  |                 updateResolutionOptions() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Update default resolution, default popup resolution & mobile data resolution options. | ||||||
|  |      * <br></br> | ||||||
|  |      * Show high resolutions when "Show higher resolution" option is enabled. | ||||||
|  |      * Set default resolution to "best resolution" when "Show higher resolution" option | ||||||
|  |      * is disabled. | ||||||
|  |      */ | ||||||
|  |     private fun updateResolutionOptions() { | ||||||
|  |         val resources = resources | ||||||
|  |         val showHigherResolutions = preferenceManager.getSharedPreferences() | ||||||
|  |             ?.getBoolean(resources.getString(R.string.show_higher_resolutions_key), false) ?: false | ||||||
|  |  | ||||||
|  |         // get sorted resolution lists | ||||||
|  |         val resolutionListDescriptions = ListHelper.getSortedResolutionList( | ||||||
|  |             resources, | ||||||
|  |             R.array.resolution_list_description, | ||||||
|  |             R.array.high_resolution_list_descriptions, | ||||||
|  |             showHigherResolutions, | ||||||
|  |         ) | ||||||
|  |         val resolutionListValues = ListHelper.getSortedResolutionList( | ||||||
|  |             resources, | ||||||
|  |             R.array.resolution_list_values, | ||||||
|  |             R.array.high_resolution_list_values, | ||||||
|  |             showHigherResolutions, | ||||||
|  |         ) | ||||||
|  |         val limitDataUsageResolutionValues = ListHelper.getSortedResolutionList( | ||||||
|  |             resources, | ||||||
|  |             R.array.limit_data_usage_values_list, | ||||||
|  |             R.array.high_resolution_limit_data_usage_values_list, | ||||||
|  |             showHigherResolutions, | ||||||
|  |         ) | ||||||
|  |         val limitDataUsageResolutionDescriptions = ListHelper | ||||||
|  |             .getSortedResolutionList( | ||||||
|  |                 resources, | ||||||
|  |                 R.array.limit_data_usage_description_list, | ||||||
|  |                 R.array.high_resolution_list_descriptions, | ||||||
|  |                 showHigherResolutions, | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         // get resolution preferences | ||||||
|  |         val defaultResolution = findPreference<ListPreference>( | ||||||
|  |             getString(R.string.default_resolution_key) | ||||||
|  |         ) | ||||||
|  |         val defaultPopupResolution = findPreference<ListPreference>( | ||||||
|  |             getString(R.string.default_popup_resolution_key) | ||||||
|  |         ) | ||||||
|  |         val mobileDataResolution = findPreference<ListPreference>( | ||||||
|  |             getString(R.string.limit_mobile_data_usage_key) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         // update resolution preferences with new resolutions, entries & values for each | ||||||
|  |         defaultResolution?.entries = resolutionListDescriptions.toTypedArray<String>() | ||||||
|  |         defaultResolution?.entryValues = resolutionListValues.toTypedArray<String>() | ||||||
|  |         defaultPopupResolution?.entries = resolutionListDescriptions.toTypedArray<String>() | ||||||
|  |         defaultPopupResolution?.entryValues = resolutionListValues.toTypedArray<String>() | ||||||
|  |         mobileDataResolution?.entries = limitDataUsageResolutionDescriptions.toTypedArray<String>() | ||||||
|  |         mobileDataResolution?.entryValues = | ||||||
|  |             limitDataUsageResolutionValues.toTypedArray<String>() | ||||||
|  |  | ||||||
|  |         // if "Show higher resolution" option is disabled, | ||||||
|  |         // set default resolution to "best resolution" | ||||||
|  |         if (!showHigherResolutions) { | ||||||
|  |             if (defaultResolution != null && ListHelper.isHighResolutionSelected( | ||||||
|  |                     defaultResolution.value, | ||||||
|  |                     R.array.high_resolution_list_values, | ||||||
|  |                     resources | ||||||
|  |                 ) | ||||||
|  |             ) { | ||||||
|  |                 defaultResolution.setValueIndex(0) | ||||||
|  |             } | ||||||
|  |             if (defaultPopupResolution != null && ListHelper.isHighResolutionSelected( | ||||||
|  |                     defaultPopupResolution.value, | ||||||
|  |                     R.array.high_resolution_list_values, | ||||||
|  |                     resources, | ||||||
|  |                 ) | ||||||
|  |             ) { | ||||||
|  |                 defaultPopupResolution.setValueIndex(0) | ||||||
|  |             } | ||||||
|  |             if (mobileDataResolution != null && ListHelper.isHighResolutionSelected( | ||||||
|  |                     mobileDataResolution.value, | ||||||
|  |                     R.array.high_resolution_limit_data_usage_values_list, | ||||||
|  |                     resources, | ||||||
|  |                 ) | ||||||
|  |             ) { | ||||||
|  |                 mobileDataResolution.setValueIndex(0) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Update fast-forward/-rewind seek duration options | ||||||
|  |      * according to language and inexact seek setting. | ||||||
|  |      * Exoplayer can't seek 5 seconds in audio when using inexact seek. | ||||||
|  |      */ | ||||||
|  |     private fun updateSeekOptions() { | ||||||
|  |         // initializing R.array.seek_duration_description to display the translation of seconds | ||||||
|  |         val durationsValues = resources.getStringArray(R.array.seek_duration_value) | ||||||
|  |         val displayedDurationValues = LinkedList<String>() | ||||||
|  |         val displayedDescriptionValues = LinkedList<String>() | ||||||
|  |         val inexactSeek = preferenceManager.getSharedPreferences() | ||||||
|  |             ?.getBoolean(resources.getString(R.string.use_inexact_seek_key), false) ?: false | ||||||
|  |         for (durationsValue in durationsValues) { | ||||||
|  |             val currentDurationValue = durationsValue.toInt() / DateUtils.SECOND_IN_MILLIS.toInt() | ||||||
|  |             if (inexactSeek && currentDurationValue % 10 == 5) { | ||||||
|  |                 continue | ||||||
|  |             } | ||||||
|  |             displayedDurationValues.add(durationsValue) | ||||||
|  |             try { | ||||||
|  |                 displayedDescriptionValues.add( | ||||||
|  |                     String.format( | ||||||
|  |                         resources.getQuantityString(R.plurals.seconds, currentDurationValue), | ||||||
|  |                         currentDurationValue | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|  |             } catch (ignored: NotFoundException) { | ||||||
|  |                 // if this happens, the translation is missing, | ||||||
|  |                 // and the english string will be displayed instead | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         findPreference<ListPreference>(getString(R.string.seek_duration_key))?.apply { | ||||||
|  |             entryValues = displayedDurationValues.toTypedArray<CharSequence>() | ||||||
|  |             entries = displayedDescriptionValues.toTypedArray<CharSequence>() | ||||||
|  |             val selectedDuration = value.toLong() | ||||||
|  |             if (inexactSeek && selectedDuration / DateUtils.SECOND_IN_MILLIS % 10 == 5L) { | ||||||
|  |                 val newDuration = selectedDuration / DateUtils.SECOND_IN_MILLIS + 5 | ||||||
|  |                 value = (newDuration * DateUtils.SECOND_IN_MILLIS).toString() | ||||||
|  |                 Toast.makeText( | ||||||
|  |                     context, | ||||||
|  |                     getString(R.string.new_seek_duration_toast, newDuration), | ||||||
|  |                     Toast.LENGTH_LONG, | ||||||
|  |                 ).show() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun onResume() { | ||||||
|  |         super.onResume() | ||||||
|  |         preferenceManager.getSharedPreferences()?.registerOnSharedPreferenceChangeListener(listener) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun onPause() { | ||||||
|  |         super.onPause() | ||||||
|  |         preferenceManager.getSharedPreferences()?.unregisterOnSharedPreferenceChangeListener(listener) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun onPreferenceTreeClick(preference: Preference): Boolean { | ||||||
|  |         if (getString(R.string.caption_settings_key) == preference.key) { | ||||||
|  |             try { | ||||||
|  |                 startActivity(Intent(Settings.ACTION_CAPTIONING_SETTINGS)) | ||||||
|  |             } catch (error: ActivityNotFoundException) { | ||||||
|  |                 Toast.makeText(requireContext(), R.string.general_error, Toast.LENGTH_SHORT).show() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return super.onPreferenceTreeClick(preference) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -30,11 +30,11 @@ public final class SettingsResourceRegistry { | |||||||
|  |  | ||||||
|     private SettingsResourceRegistry() { |     private SettingsResourceRegistry() { | ||||||
|         add(MainSettingsV2Fragment.class, R.xml.main_settings_v2).setSearchable(false); |         add(MainSettingsV2Fragment.class, R.xml.main_settings_v2).setSearchable(false); | ||||||
|  |         add(PlayerSettingsFragment.class, R.xml.player_settings); | ||||||
|  |  | ||||||
|         // Before redesign settings arrangement. These should be cleared once the |         // Before redesign settings arrangement. These should be cleared once the | ||||||
|         // settings_layout_redesign_key is approved and enabled by default. |         // settings_layout_redesign_key is approved and enabled by default. | ||||||
|         add(MainSettingsFragment.class, R.xml.main_settings).setSearchable(false); |         add(MainSettingsFragment.class, R.xml.main_settings).setSearchable(false); | ||||||
|  |  | ||||||
|         add(AppearanceSettingsFragment.class, R.xml.appearance_settings); |         add(AppearanceSettingsFragment.class, R.xml.appearance_settings); | ||||||
|         add(ContentSettingsFragment.class, R.xml.content_settings); |         add(ContentSettingsFragment.class, R.xml.content_settings); | ||||||
|         add(DebugSettingsFragment.class, R.xml.debug_settings).setSearchable(false); |         add(DebugSettingsFragment.class, R.xml.debug_settings).setSearchable(false); | ||||||
|   | |||||||
| @@ -846,4 +846,6 @@ | |||||||
|     </plurals> |     </plurals> | ||||||
|     <string name="show_more">Show more</string> |     <string name="show_more">Show more</string> | ||||||
|     <string name="show_less">Show less</string> |     <string name="show_less">Show less</string> | ||||||
|  |     <!-- Settings redesign --> | ||||||
|  |     <string name="settings_category_resolution_and_format_title">Resolution and format</string> | ||||||
| </resources> | </resources> | ||||||
|   | |||||||
| @@ -4,6 +4,11 @@ | |||||||
|     android:key="general_preferences" |     android:key="general_preferences" | ||||||
|     android:title="@string/settings"> |     android:title="@string/settings"> | ||||||
|  |  | ||||||
|  |     <PreferenceScreen | ||||||
|  |         android:fragment="org.schabi.newpipe.settings.PlayerSettingsFragment" | ||||||
|  |         android:title="@string/settings_category_player_title" | ||||||
|  |         app:iconSpaceReserved="false" /> | ||||||
|  |  | ||||||
|     <PreferenceScreen |     <PreferenceScreen | ||||||
|         android:fragment="org.schabi.newpipe.settings.DebugSettingsFragment" |         android:fragment="org.schabi.newpipe.settings.DebugSettingsFragment" | ||||||
|         android:key="@string/debug_pref_screen_key" |         android:key="@string/debug_pref_screen_key" | ||||||
|   | |||||||
							
								
								
									
										150
									
								
								app/src/main/res/xml/player_settings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								app/src/main/res/xml/player_settings.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|  |     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||||
|  |     android:title="@string/settings_category_player_title"> | ||||||
|  |  | ||||||
|  |     <PreferenceCategory | ||||||
|  |         android:layout="@layout/settings_category_header_layout" | ||||||
|  |         android:title="@string/settings_category_resolution_and_format_title" | ||||||
|  |         app:iconSpaceReserved="false" | ||||||
|  |         app:singleLineTitle="false"> | ||||||
|  |  | ||||||
|  |         <ListPreference | ||||||
|  |             android:defaultValue="@string/default_resolution_value" | ||||||
|  |             android:entries="@array/resolution_list_description" | ||||||
|  |             android:entryValues="@array/resolution_list_values" | ||||||
|  |             android:key="@string/default_resolution_key" | ||||||
|  |             android:title="@string/default_resolution_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" | ||||||
|  |             app:useSimpleSummaryProvider="true" /> | ||||||
|  |  | ||||||
|  |         <ListPreference | ||||||
|  |             android:defaultValue="@string/default_popup_resolution_value" | ||||||
|  |             android:entries="@array/resolution_list_description" | ||||||
|  |             android:entryValues="@array/resolution_list_values" | ||||||
|  |             android:key="@string/default_popup_resolution_key" | ||||||
|  |             android:title="@string/default_popup_resolution_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" | ||||||
|  |             app:useSimpleSummaryProvider="true" /> | ||||||
|  |  | ||||||
|  |         <ListPreference | ||||||
|  |             android:defaultValue="@string/limit_mobile_data_usage_value" | ||||||
|  |             android:entries="@array/limit_data_usage_description_list" | ||||||
|  |             android:entryValues="@array/limit_data_usage_values_list" | ||||||
|  |             android:key="@string/limit_mobile_data_usage_key" | ||||||
|  |             android:title="@string/limit_mobile_data_usage_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" | ||||||
|  |             app:useSimpleSummaryProvider="true" /> | ||||||
|  |  | ||||||
|  |         <SwitchPreferenceCompat | ||||||
|  |             android:defaultValue="false" | ||||||
|  |             android:key="@string/show_higher_resolutions_key" | ||||||
|  |             android:summary="@string/show_higher_resolutions_summary" | ||||||
|  |             android:title="@string/show_higher_resolutions_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" /> | ||||||
|  |  | ||||||
|  |         <ListPreference | ||||||
|  |             android:defaultValue="@string/default_video_format_value" | ||||||
|  |             android:entries="@array/video_format_description_list" | ||||||
|  |             android:entryValues="@array/video_format_values_list" | ||||||
|  |             android:key="@string/default_video_format_key" | ||||||
|  |             android:title="@string/default_video_format_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" | ||||||
|  |             app:useSimpleSummaryProvider="true" /> | ||||||
|  |  | ||||||
|  |         <ListPreference | ||||||
|  |             android:defaultValue="@string/default_audio_format_value" | ||||||
|  |             android:entries="@array/audio_format_description_list" | ||||||
|  |             android:entryValues="@array/audio_format_values_list" | ||||||
|  |             android:key="@string/default_audio_format_key" | ||||||
|  |             android:title="@string/default_audio_format_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" | ||||||
|  |             app:useSimpleSummaryProvider="true" /> | ||||||
|  |  | ||||||
|  |         <SwitchPreferenceCompat | ||||||
|  |             android:defaultValue="false" | ||||||
|  |             android:key="@string/prefer_original_audio_key" | ||||||
|  |             android:summary="@string/prefer_original_audio_summary" | ||||||
|  |             android:title="@string/prefer_original_audio_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" /> | ||||||
|  |  | ||||||
|  |         <SwitchPreferenceCompat | ||||||
|  |             android:defaultValue="false" | ||||||
|  |             android:key="@string/prefer_descriptive_audio_key" | ||||||
|  |             android:summary="@string/prefer_descriptive_audio_summary" | ||||||
|  |             android:title="@string/prefer_descriptive_audio_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" /> | ||||||
|  |  | ||||||
|  |         <PreferenceScreen | ||||||
|  |             android:fragment="org.schabi.newpipe.settings.ExoPlayerSettingsFragment" | ||||||
|  |             android:key="@string/exoplayer_settings_key" | ||||||
|  |             android:summary="@string/settings_category_exoplayer_summary" | ||||||
|  |             android:title="@string/settings_category_exoplayer_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" /> | ||||||
|  |     </PreferenceCategory> | ||||||
|  |  | ||||||
|  |     <PreferenceCategory | ||||||
|  |         android:layout="@layout/settings_category_header_layout" | ||||||
|  |         android:title="@string/settings_category_player_title" | ||||||
|  |         app:iconSpaceReserved="false" | ||||||
|  |         app:singleLineTitle="false"> | ||||||
|  |  | ||||||
|  |         <SwitchPreferenceCompat | ||||||
|  |             android:defaultValue="false" | ||||||
|  |             android:key="@string/use_external_video_player_key" | ||||||
|  |             android:summary="@string/use_external_video_player_summary" | ||||||
|  |             android:title="@string/use_external_video_player_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" /> | ||||||
|  |  | ||||||
|  |         <SwitchPreferenceCompat | ||||||
|  |             android:defaultValue="false" | ||||||
|  |             android:key="@string/use_external_audio_player_key" | ||||||
|  |             android:title="@string/use_external_audio_player_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" /> | ||||||
|  |  | ||||||
|  |         <SwitchPreferenceCompat | ||||||
|  |             android:defaultValue="false" | ||||||
|  |             android:key="@string/show_play_with_kodi_key" | ||||||
|  |             android:summary="@string/show_play_with_kodi_summary" | ||||||
|  |             android:title="@string/show_play_with_kodi_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" /> | ||||||
|  |  | ||||||
|  |         <ListPreference | ||||||
|  |             android:layout_width="wrap_content" | ||||||
|  |             android:layout_height="wrap_content" | ||||||
|  |             android:defaultValue="seekbar_preview_thumbnail_high_quality" | ||||||
|  |             android:entries="@array/seekbar_preview_thumbnail_type_description" | ||||||
|  |             android:entryValues="@array/seekbar_preview_thumbnail_type_key" | ||||||
|  |             android:key="@string/seekbar_preview_thumbnail_key" | ||||||
|  |             android:title="@string/seekbar_preview_thumbnail_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" | ||||||
|  |             app:useSimpleSummaryProvider="true" /> | ||||||
|  |  | ||||||
|  |         <Preference | ||||||
|  |             android:key="@string/caption_settings_key" | ||||||
|  |             android:summary="@string/caption_setting_description" | ||||||
|  |             android:title="@string/caption_setting_title" | ||||||
|  |             app:singleLineTitle="false" | ||||||
|  |             app:iconSpaceReserved="false" /> | ||||||
|  |  | ||||||
|  |         <PreferenceScreen | ||||||
|  |             android:key="@string/player_notification_screen_key" | ||||||
|  |             android:summary="@string/settings_category_player_notification_summary" | ||||||
|  |             android:title="@string/settings_category_player_notification_title" | ||||||
|  |             app:iconSpaceReserved="false" | ||||||
|  |             app:singleLineTitle="false" /> | ||||||
|  |     </PreferenceCategory> | ||||||
|  | </PreferenceScreen> | ||||||
		Reference in New Issue
	
	Block a user
	 Siddhesh Naik
					Siddhesh Naik