Fix 3419077: implement new volume control in Settings.
Change-Id: Ia4b803315382d59ae231c26187afaceb69397952
This commit is contained in:
@@ -23,12 +23,14 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:paddingBottom="20dip">
|
android:paddingBottom="12dip"
|
||||||
|
android:paddingTop="12dip">
|
||||||
|
|
||||||
<ImageView android:id="@android:id/icon"
|
<ImageView android:id="@android:id/icon"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingTop="20dip" />
|
android:paddingTop="20dip"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/ringtone_label"
|
android:id="@+id/ringtone_label"
|
||||||
@@ -40,6 +42,7 @@
|
|||||||
android:paddingRight="20dip" />
|
android:paddingRight="20dip" />
|
||||||
|
|
||||||
<!-- Used for the ring volume. This is what the superclass VolumePreference uses. -->
|
<!-- Used for the ring volume. This is what the superclass VolumePreference uses. -->
|
||||||
|
<!-- TODO - is this used? -->
|
||||||
<SeekBar android:id="@*android:id/seekbar"
|
<SeekBar android:id="@*android:id/seekbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -48,35 +51,26 @@
|
|||||||
android:paddingRight="20dip" />
|
android:paddingRight="20dip" />
|
||||||
|
|
||||||
<!-- Used for the media volume -->
|
<!-- Used for the media volume -->
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/media_volume_title"
|
android:orientation="horizontal"
|
||||||
android:paddingTop="10dip"
|
android:gravity="center_vertical">
|
||||||
android:paddingLeft="20dip"
|
|
||||||
android:paddingRight="20dip" />
|
|
||||||
<SeekBar android:id="@+id/media_volume_seekbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="2dip"
|
|
||||||
android:paddingLeft="20dip"
|
|
||||||
android:paddingRight="20dip" />
|
|
||||||
|
|
||||||
<!-- Used for the alarm volume -->
|
<ImageView android:id="@+id/volume_mute_button"
|
||||||
<TextView
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"/>
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/alarm_volume_title"
|
|
||||||
android:paddingTop="10dip"
|
|
||||||
android:paddingLeft="20dip"
|
|
||||||
android:paddingRight="20dip" />
|
|
||||||
<SeekBar android:id="@+id/alarm_volume_seekbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="2dip"
|
|
||||||
android:paddingLeft="20dip"
|
|
||||||
android:paddingRight="20dip" />
|
|
||||||
|
|
||||||
|
<SeekBar android:id="@+id/media_volume_seekbar"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:paddingTop="2dip"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- TODO - is this used? -->
|
||||||
<CheckBox android:id="@+id/same_notification_volume"
|
<CheckBox android:id="@+id/same_notification_volume"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -86,21 +80,55 @@
|
|||||||
android:layout_marginLeft="20dip"
|
android:layout_marginLeft="20dip"
|
||||||
android:layout_marginRight="20dip" />
|
android:layout_marginRight="20dip" />
|
||||||
|
|
||||||
<TextView android:id="@+id/notification_volume_title"
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="1px"
|
||||||
android:text="@string/notification_volume_title"
|
android:background="#1bffffff"
|
||||||
android:paddingTop="6dip"
|
android:layout_marginTop="16dip"
|
||||||
android:paddingLeft="20dip"
|
android:layout_marginBottom="16dip"/>
|
||||||
android:paddingRight="20dip" />
|
|
||||||
|
|
||||||
<!-- Used for the notification volume -->
|
<!-- Used for the notification volume -->
|
||||||
<SeekBar android:id="@+id/notification_volume_seekbar"
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingTop="2dip"
|
android:orientation="horizontal">
|
||||||
android:paddingLeft="20dip"
|
|
||||||
android:paddingRight="20dip" />
|
<ImageView android:id="@+id/notification_mute_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<SeekBar android:id="@+id/notification_volume_seekbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="2dip"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1px"
|
||||||
|
android:background="#1bffffff"
|
||||||
|
android:layout_marginTop="16dip"
|
||||||
|
android:layout_marginBottom="16dip"/>
|
||||||
|
|
||||||
|
<!-- Used for the alarm volume -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView android:id="@+id/alarm_mute_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<SeekBar android:id="@+id/alarm_volume_seekbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="2dip"
|
||||||
|
android:paddingLeft="20dip"
|
||||||
|
android:paddingRight="20dip" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@@ -16,20 +16,34 @@
|
|||||||
|
|
||||||
package com.android.settings;
|
package com.android.settings;
|
||||||
|
|
||||||
|
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
|
||||||
|
import static android.provider.Telephony.Intents.SPN_STRINGS_UPDATED_ACTION;
|
||||||
|
|
||||||
|
import com.android.internal.telephony.TelephonyIntents;
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Message;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.preference.VolumePreference;
|
import android.preference.VolumePreference;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@@ -38,12 +52,15 @@ import android.widget.TextView;
|
|||||||
* notification volume.
|
* notification volume.
|
||||||
*/
|
*/
|
||||||
public class RingerVolumePreference extends VolumePreference implements
|
public class RingerVolumePreference extends VolumePreference implements
|
||||||
CheckBox.OnCheckedChangeListener {
|
CheckBox.OnCheckedChangeListener, OnClickListener {
|
||||||
private static final String TAG = "RingerVolumePreference";
|
private static final String TAG = "RingerVolumePreference";
|
||||||
|
private static final int MSG_RINGER_MODE_CHANGED = 101;
|
||||||
|
|
||||||
private CheckBox mNotificationsUseRingVolumeCheckbox;
|
private CheckBox mNotificationsUseRingVolumeCheckbox;
|
||||||
private SeekBarVolumizer [] mSeekBarVolumizer;
|
private SeekBarVolumizer [] mSeekBarVolumizer;
|
||||||
private boolean mIgnoreVolumeKeys;
|
private boolean mIgnoreVolumeKeys;
|
||||||
|
|
||||||
|
// These arrays must all match in length and order
|
||||||
private static final int[] SEEKBAR_ID = new int[] {
|
private static final int[] SEEKBAR_ID = new int[] {
|
||||||
R.id.notification_volume_seekbar,
|
R.id.notification_volume_seekbar,
|
||||||
R.id.media_volume_seekbar,
|
R.id.media_volume_seekbar,
|
||||||
@@ -51,9 +68,9 @@ public class RingerVolumePreference extends VolumePreference implements
|
|||||||
};
|
};
|
||||||
|
|
||||||
private static final int[] NEED_VOICE_CAPABILITY_ID = new int[] {
|
private static final int[] NEED_VOICE_CAPABILITY_ID = new int[] {
|
||||||
R.id.ringtone_label,
|
R.id.ringtone_label,
|
||||||
com.android.internal.R.id.seekbar,
|
com.android.internal.R.id.seekbar,
|
||||||
R.id.same_notification_volume
|
R.id.same_notification_volume
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final int[] SEEKBAR_TYPE = new int[] {
|
private static final int[] SEEKBAR_TYPE = new int[] {
|
||||||
@@ -61,8 +78,63 @@ public class RingerVolumePreference extends VolumePreference implements
|
|||||||
AudioManager.STREAM_MUSIC,
|
AudioManager.STREAM_MUSIC,
|
||||||
AudioManager.STREAM_ALARM
|
AudioManager.STREAM_ALARM
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static final int[] CHECKBOX_VIEW_ID = new int[] {
|
||||||
|
R.id.notification_mute_button,
|
||||||
|
R.id.volume_mute_button,
|
||||||
|
R.id.alarm_mute_button
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final int[] SEEKBAR_MUTED_RES_ID = new int[] {
|
||||||
|
com.android.internal.R.drawable.ic_audio_notification_mute,
|
||||||
|
com.android.internal.R.drawable.ic_audio_vol_mute,
|
||||||
|
com.android.internal.R.drawable.ic_audio_alarm_mute
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final int[] SEEKBAR_UNMUTED_RES_ID = new int[] {
|
||||||
|
com.android.internal.R.drawable.ic_audio_notification,
|
||||||
|
com.android.internal.R.drawable.ic_audio_vol,
|
||||||
|
com.android.internal.R.drawable.ic_audio_alarm
|
||||||
|
};
|
||||||
|
|
||||||
|
private ImageView[] mCheckBoxes = new ImageView[SEEKBAR_MUTED_RES_ID.length];
|
||||||
|
private SeekBar[] mSeekBars = new SeekBar[SEEKBAR_ID.length];
|
||||||
|
|
||||||
|
private Handler mHandler = new Handler() {
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
updateSlidersAndMutedStates();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createActionButtons() {
|
||||||
|
setPositiveButtonText(android.R.string.ok);
|
||||||
|
setNegativeButtonText(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSlidersAndMutedStates() {
|
||||||
|
for (int i = 0; i < SEEKBAR_TYPE.length; i++) {
|
||||||
|
int streamType = SEEKBAR_TYPE[i];
|
||||||
|
boolean muted = mAudioManager.isStreamMute(streamType);
|
||||||
|
|
||||||
|
if (mCheckBoxes[i] != null) {
|
||||||
|
mCheckBoxes[i].setImageResource(
|
||||||
|
muted ? SEEKBAR_MUTED_RES_ID[i] : SEEKBAR_UNMUTED_RES_ID[i]);
|
||||||
|
}
|
||||||
|
if (mSeekBars[i] != null) {
|
||||||
|
mSeekBars[i].setEnabled(!muted);
|
||||||
|
final int volume = muted ? mAudioManager.getLastAudibleStreamVolume(streamType)
|
||||||
|
: mAudioManager.getStreamVolume(streamType);
|
||||||
|
mSeekBars[i].setProgress(volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BroadcastReceiver mRingModeChangedReceiver;
|
||||||
|
private AudioManager mAudioManager;
|
||||||
|
|
||||||
//private SeekBarVolumizer mNotificationSeekBarVolumizer;
|
//private SeekBarVolumizer mNotificationSeekBarVolumizer;
|
||||||
private TextView mNotificationVolumeTitle;
|
//private TextView mNotificationVolumeTitle;
|
||||||
|
|
||||||
public RingerVolumePreference(Context context, AttributeSet attrs) {
|
public RingerVolumePreference(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
@@ -71,10 +143,12 @@ public class RingerVolumePreference extends VolumePreference implements
|
|||||||
setStreamType(AudioManager.STREAM_RING);
|
setStreamType(AudioManager.STREAM_RING);
|
||||||
|
|
||||||
setDialogLayoutResource(R.layout.preference_dialog_ringervolume);
|
setDialogLayoutResource(R.layout.preference_dialog_ringervolume);
|
||||||
setDialogIcon(R.drawable.ic_settings_sound);
|
//setDialogIcon(R.drawable.ic_settings_sound);
|
||||||
|
|
||||||
mSeekBarVolumizer = new SeekBarVolumizer[SEEKBAR_ID.length];
|
mSeekBarVolumizer = new SeekBarVolumizer[SEEKBAR_ID.length];
|
||||||
mIgnoreVolumeKeys = !Utils.isVoiceCapable(context);
|
mIgnoreVolumeKeys = !Utils.isVoiceCapable(context);
|
||||||
|
|
||||||
|
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -83,6 +157,7 @@ public class RingerVolumePreference extends VolumePreference implements
|
|||||||
|
|
||||||
for (int i = 0; i < SEEKBAR_ID.length; i++) {
|
for (int i = 0; i < SEEKBAR_ID.length; i++) {
|
||||||
SeekBar seekBar = (SeekBar) view.findViewById(SEEKBAR_ID[i]);
|
SeekBar seekBar = (SeekBar) view.findViewById(SEEKBAR_ID[i]);
|
||||||
|
mSeekBars[i] = seekBar;
|
||||||
if (SEEKBAR_TYPE[i] == AudioManager.STREAM_MUSIC) {
|
if (SEEKBAR_TYPE[i] == AudioManager.STREAM_MUSIC) {
|
||||||
mSeekBarVolumizer[i] = new SeekBarVolumizer(getContext(), seekBar,
|
mSeekBarVolumizer[i] = new SeekBarVolumizer(getContext(), seekBar,
|
||||||
SEEKBAR_TYPE[i], getMediaVolumeUri(getContext()));
|
SEEKBAR_TYPE[i], getMediaVolumeUri(getContext()));
|
||||||
@@ -92,7 +167,7 @@ public class RingerVolumePreference extends VolumePreference implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mNotificationVolumeTitle = (TextView) view.findViewById(R.id.notification_volume_title);
|
//mNotificationVolumeTitle = (TextView) view.findViewById(R.id.notification_volume_title);
|
||||||
mNotificationsUseRingVolumeCheckbox =
|
mNotificationsUseRingVolumeCheckbox =
|
||||||
(CheckBox) view.findViewById(R.id.same_notification_volume);
|
(CheckBox) view.findViewById(R.id.same_notification_volume);
|
||||||
mNotificationsUseRingVolumeCheckbox.setOnCheckedChangeListener(this);
|
mNotificationsUseRingVolumeCheckbox.setOnCheckedChangeListener(this);
|
||||||
@@ -103,6 +178,32 @@ public class RingerVolumePreference extends VolumePreference implements
|
|||||||
Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1) == 1);
|
Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1) == 1);
|
||||||
setNotificationVolumeVisibility(!mNotificationsUseRingVolumeCheckbox.isChecked());
|
setNotificationVolumeVisibility(!mNotificationsUseRingVolumeCheckbox.isChecked());
|
||||||
disableSettingsThatNeedVoice(view);
|
disableSettingsThatNeedVoice(view);
|
||||||
|
|
||||||
|
// Register callbacks for mute/unmute buttons
|
||||||
|
for (int i = 0; i < mCheckBoxes.length; i++) {
|
||||||
|
ImageView checkbox = (ImageView) view.findViewById(CHECKBOX_VIEW_ID[i]);
|
||||||
|
checkbox.setOnClickListener(this);
|
||||||
|
mCheckBoxes[i] = checkbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load initial states from AudioManager
|
||||||
|
updateSlidersAndMutedStates();
|
||||||
|
|
||||||
|
// Listen for updates from AudioManager
|
||||||
|
if (mRingModeChangedReceiver == null) {
|
||||||
|
final IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
|
||||||
|
mRingModeChangedReceiver = new BroadcastReceiver() {
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
final String action = intent.getAction();
|
||||||
|
if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
|
||||||
|
intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
getContext().registerReceiver(mRingModeChangedReceiver, filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Uri getMediaVolumeUri(Context context) {
|
private Uri getMediaVolumeUri(Context context) {
|
||||||
@@ -147,10 +248,8 @@ public class RingerVolumePreference extends VolumePreference implements
|
|||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
// The user wants the notification to be same as ring, so do a
|
// The user wants the notification to be same as ring, so do a
|
||||||
// one-time sync right now
|
// one-time sync right now
|
||||||
AudioManager audioManager = (AudioManager) getContext()
|
mAudioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION,
|
||||||
.getSystemService(Context.AUDIO_SERVICE);
|
mAudioManager.getStreamVolume(AudioManager.STREAM_RING), 0);
|
||||||
audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION,
|
|
||||||
audioManager.getStreamVolume(AudioManager.STREAM_RING), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +283,7 @@ public class RingerVolumePreference extends VolumePreference implements
|
|||||||
mSeekBarVolumizer[0].getSeekBar().setVisibility(
|
mSeekBarVolumizer[0].getSeekBar().setVisibility(
|
||||||
visible ? View.VISIBLE : View.GONE);
|
visible ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
mNotificationVolumeTitle.setVisibility(visible ? View.VISIBLE : View.GONE);
|
// mNotificationVolumeTitle.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanup() {
|
private void cleanup() {
|
||||||
@@ -199,6 +298,10 @@ public class RingerVolumePreference extends VolumePreference implements
|
|||||||
mSeekBarVolumizer[i] = null;
|
mSeekBarVolumizer[i] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mRingModeChangedReceiver != null) {
|
||||||
|
getContext().unregisterReceiver(mRingModeChangedReceiver);
|
||||||
|
mRingModeChangedReceiver = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -286,4 +389,17 @@ public class RingerVolumePreference extends VolumePreference implements
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onClick(View v) {
|
||||||
|
// Touching any of the mute buttons causes us to get the state from the system and toggle it
|
||||||
|
switch(mAudioManager.getRingerMode()) {
|
||||||
|
case AudioManager.RINGER_MODE_NORMAL:
|
||||||
|
mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
|
||||||
|
break;
|
||||||
|
case AudioManager.RINGER_MODE_VIBRATE:
|
||||||
|
case AudioManager.RINGER_MODE_SILENT:
|
||||||
|
mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user