Skip to content

Commit

Permalink
custom rationale dialogs for permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
skustra committed Feb 23, 2023
1 parent 3a126c9 commit 5d1a2c4
Show file tree
Hide file tree
Showing 9 changed files with 438 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
Expand Down Expand Up @@ -170,13 +171,15 @@ private void executePreGrantedPermissionsRequest(PermissionsRequest request) {

@SuppressWarnings("ConstantConditions")
private void executePermissionsRequestWithRationale(PermissionsRequest request) {
RationaleDialog.createFor(permissionObject.getContext(), rationaleDialogMessage, rationalDialogHeader)
.setPositiveButton(R.string.Permissions_continue, (dialog, which) -> executePermissionsRequest(request))
.setNegativeButton(R.string.Permissions_not_now, (dialog, which) -> executeNoPermissionsRequest(request))
.setCancelable(rationaleDialogCancelable)
.show()
.getWindow()
.setLayout((int)(permissionObject.getWindowWidth() * .75), ViewGroup.LayoutParams.WRAP_CONTENT);
AlertDialog dialog = RationaleDialog.createNonMsgDialog(permissionObject.getContext(),
rationaleDialogMessage,
R.string.Permissions_continue,
R.string.Permissions_not_now,
() -> executePermissionsRequest(request),
() -> executeNoPermissionsRequest(request),
null);
dialog.setCancelable(rationaleDialogCancelable);
dialog.show();
}

private void executePermissionsRequest(PermissionsRequest request) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,66 +1,36 @@
package org.thoughtcrime.securesms.permissions;


import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.text.method.ScrollingMovementMethod;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;

import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;

import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.signal.core.util.logging.Log;

import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import pigeon.components.Mp02CustomDialog;

public class RationaleDialog {

public static MaterialAlertDialogBuilder createFor(@NonNull Context context, @NonNull String message, @DrawableRes int... drawables) {
View view = LayoutInflater.from(context).inflate(R.layout.permissions_rationale_dialog, null);
ViewGroup header = view.findViewById(R.id.header_container);
TextView text = view.findViewById(R.id.message);

for (int i=0;i<drawables.length;i++) {
Drawable drawable = ContextCompat.getDrawable(context, drawables[i]);
DrawableCompat.setTint(drawable, ContextCompat.getColor(context, R.color.white));
ImageView imageView = new ImageView(context);
imageView.setImageDrawable(drawable);
imageView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

header.addView(imageView);

if (i != drawables.length - 1) {
TextView plus = new TextView(context);
plus.setText("+");
plus.setTextSize(TypedValue.COMPLEX_UNIT_SP, 40);
plus.setTextColor(Color.WHITE);

LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(ViewUtil.dpToPx(context, 20), 0, ViewUtil.dpToPx(context, 20), 0);

plus.setLayoutParams(layoutParams);
header.addView(plus);
}
private static final String TAG = "RationaleDialog";

public static AlertDialog createNonMsgDialog(@NonNull Context context,
String title,
int positiveResId,
int negativeResId,
Mp02CustomDialog.Mp02DialogKeyListener positiveListener,
Mp02CustomDialog.Mp02DialogKeyListener negativeListener,
Mp02CustomDialog.Mp02OnBackKeyListener backKeyListenr)
{
Mp02CustomDialog dialog = new Mp02CustomDialog(context);
if (title == null || title.equals("")) {
Log.e(TAG, "Dialog title is NULL!");
} else {
dialog.setMessage(title);
}

text.setText(message);
text.setMovementMethod(new ScrollingMovementMethod());

return new MaterialAlertDialogBuilder(context,
ThemeUtil.isDarkTheme(context) ? R.style.Theme_Signal_AlertDialog_Dark_Cornered
: R.style.Theme_Signal_AlertDialog_Light_Cornered)
.setView(view);
dialog.setPositiveListener(positiveResId, positiveListener);
dialog.setNegativeListener(negativeResId, negativeListener);
dialog.setBackKeyListener(backKeyListenr);
return dialog;
}

}
243 changes: 243 additions & 0 deletions app/src/main/java/pigeon/components/Mp02CustomDialog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
package pigeon.components;

import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.view.KeyEvent;

import org.thoughtcrime.securesms.R;

import java.lang.ref.WeakReference;

public class Mp02CustomDialog extends AlertDialog {
public static final String TAG = "Mp02CustomDialog";

private Context mContext;
private LinearLayout mLinearLayoutTop;
private LinearLayout mLinearLayoutBottom;
private TextView mTvFocusBuffer[] = new TextView[2];
private TextView mTvTopBuffer[] = new TextView[2];
private TextView mTvBottomBuffer[] = new TextView[3];
private Animation mAnimUpVisible;
private Animation mAnimUpGone;
private Animation mAnimDownVisible;
private Animation mAnimDownGone;
private ButtonHandler mHandler;

private final View.OnClickListener mDialogClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
int poi = (int) view.getTag();
if (poi == 1) {
mHandler.obtainMessage(ButtonHandler.MSG_DIALOG_POSITIVE).sendToTarget();
} else if (poi == 2) {
mHandler.obtainMessage(ButtonHandler.MSG_DIALOG_NEGATIVE).sendToTarget();
}
if(poi != 0){
mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG).sendToTarget();
}
}
};

private static final class ButtonHandler extends Handler {
private static final int MSG_DISMISS_DIALOG = -1;
private static final int MSG_DIALOG_POSITIVE = 1;
private static final int MSG_DIALOG_NEGATIVE = 2;

private WeakReference<Mp02CustomDialog> mDialog;

public ButtonHandler(Mp02CustomDialog dialog) {
mDialog = new WeakReference<>(dialog);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
default:
case MSG_DISMISS_DIALOG:
mDialog.get().dismiss();
break;
case MSG_DIALOG_POSITIVE:
if (mDialog.get().mPositiveListener != null) {
mDialog.get().mPositiveListener.onDialogKeyClicked();
}
break;
case MSG_DIALOG_NEGATIVE:
if (mDialog.get().mNegativeListener != null) {
mDialog.get().mNegativeListener.onDialogKeyClicked();
}
mDialog.get().dismiss();
break;
}
}
}

private String mMessage = "msg";
private String mPositive = "positive";
private String mNegative = "negative";
private int mPoi = 0;

public interface Mp02OnBackKeyListener {
void onBackClicked();
}

public interface Mp02DialogKeyListener {
void onDialogKeyClicked();
}

private Mp02OnBackKeyListener mBackListener;
private Mp02DialogKeyListener mPositiveListener;
private Mp02DialogKeyListener mNegativeListener;

public Mp02CustomDialog(Context context) {
super(context, R.style.Mp02_Signal_CustomDialog);
this.mContext = context;
mHandler = new ButtonHandler(this);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public void show() {
super.show();
WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
layoutParams.gravity = Gravity.BOTTOM;
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
getWindow().getDecorView().setPadding(0, 0, 0, 0);
getWindow().setAttributes(layoutParams);
setupDialog();
}


private void setupDialog() {
setContentView(R.layout.mp02_custom_dialog);
mLinearLayoutTop = findViewById(R.id.layout_top);
mLinearLayoutBottom = findViewById(R.id.layout_bottom);
//init Focus on main msg on dialog
mPoi = 0;
mTvFocusBuffer[0] = findViewById(R.id.focus_item_0);
mTvFocusBuffer[1] = findViewById(R.id.focus_item_1);
mTvFocusBuffer[0].setText(mMessage);
mTvFocusBuffer[1].setText(mMessage);
mTvFocusBuffer[1].setTag(mPoi);
mTvFocusBuffer[1].setOnClickListener(mDialogClickListener);
//init Top layout
mTvTopBuffer[0] = findViewById(R.id.unfocus_top_0);
mTvTopBuffer[1] = findViewById(R.id.unfocus_top_1);
mTvTopBuffer[0].setText(mMessage);
mTvTopBuffer[1].setText(mPositive);
//init Bottom layout
mTvBottomBuffer[0] = findViewById(R.id.unfocus_bottom_0);
mTvBottomBuffer[1] = findViewById(R.id.unfocus_bottom_1);
mTvBottomBuffer[2] = findViewById(R.id.unfocus_bottom_2);
mTvBottomBuffer[0].setText(mPositive);
mTvBottomBuffer[1].setText(mNegative);
mTvBottomBuffer[1].setText(mNegative);


mTvFocusBuffer[0].setVisibility(View.GONE);
mTvFocusBuffer[1].setVisibility(View.VISIBLE);
mLinearLayoutTop.removeAllViews();
mLinearLayoutBottom.removeAllViews();
mLinearLayoutBottom.addView(mTvBottomBuffer[0]);
mLinearLayoutBottom.addView(mTvBottomBuffer[1]);
mTvFocusBuffer[1].setTextSize(TypedValue.COMPLEX_UNIT_PX, mPoi == 0 ? 24 : 40);
//init Animation
mAnimUpVisible = AnimationUtils.loadAnimation(mContext, R.anim.mp02_up_visible);
mAnimUpGone = AnimationUtils.loadAnimation(mContext, R.anim.mp02_up_gone);
mAnimDownVisible = AnimationUtils.loadAnimation(mContext, R.anim.mp02_down_visible);
mAnimDownGone = AnimationUtils.loadAnimation(mContext, R.anim.mp02_down_gone);
}

@Override
public boolean onKeyDown(int KeyCode, KeyEvent ev) {

switch (KeyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
if (mPoi == 0) {
break;
}
mTvFocusBuffer[0].setText(getTextByPoi(mPoi));
mTvFocusBuffer[0].setVisibility(View.GONE);
mTvFocusBuffer[0].startAnimation(mAnimDownGone);
mTvFocusBuffer[1].setText(getTextByPoi(--mPoi));
mTvFocusBuffer[1].setTextSize(TypedValue.COMPLEX_UNIT_PX, mPoi == 0 ? 24 : 40);
mTvFocusBuffer[1].setVisibility(View.VISIBLE);
mTvFocusBuffer[1].startAnimation(mAnimDownVisible);
mLinearLayoutTop.getChildAt(mPoi).startAnimation(mAnimDownGone);
mLinearLayoutTop.removeViewAt(mPoi);
mLinearLayoutBottom.addView(mTvBottomBuffer[mPoi], 0);
mLinearLayoutBottom.getChildAt(0).startAnimation(mAnimDownVisible);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
if (mPoi == 2) {
break;
}
mTvFocusBuffer[0].setText(getTextByPoi(mPoi));
mTvFocusBuffer[0].setVisibility(View.GONE);
mTvFocusBuffer[0].startAnimation(mAnimUpGone);
mTvFocusBuffer[1].setText(getTextByPoi(++mPoi));
mTvFocusBuffer[1].setTextSize(TypedValue.COMPLEX_UNIT_PX, mPoi == 0 ? 24 : 40);
mTvFocusBuffer[1].setVisibility(View.VISIBLE);
mTvFocusBuffer[1].startAnimation(mAnimUpVisible);
mLinearLayoutTop.addView(mTvTopBuffer[mPoi - 1], mPoi - 1);
mLinearLayoutTop.getChildAt(mPoi - 1).startAnimation(mAnimUpVisible);
mLinearLayoutBottom.getChildAt(0).startAnimation(mAnimUpGone);
mLinearLayoutBottom.removeViewAt(0);
break;
case KeyEvent.KEYCODE_BACK:
if (mBackListener != null) {
mBackListener.onBackClicked();
}
this.dismiss();
}
mTvFocusBuffer[1].setTag(mPoi);
return super.onKeyDown(KeyCode, ev);
}

private String getTextByPoi(int poi) {
switch (poi) {
default:
case 0:
return mMessage;
case 1:
return mPositive;
case 2:
return mNegative;
}
}

public void setMessage(String msg) {
mMessage = msg;
}

public void setPositiveListener(int resId, Mp02DialogKeyListener listener) {
mPositive = mContext.getString(resId);
mPositiveListener = listener;
}

public void setNegativeListener(int resId, Mp02DialogKeyListener listener) {
mNegative = mContext.getString(resId);
mNegativeListener = listener;
}

public void setBackKeyListener(Mp02OnBackKeyListener listener) {
mBackListener = listener;
}
}
7 changes: 7 additions & 0 deletions app/src/main/res/anim/mp02_down_gone.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="0%"
android:toYDelta="100%"
android:duration="300"/>
</set>
7 changes: 7 additions & 0 deletions app/src/main/res/anim/mp02_down_visible.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="-100%"
android:toYDelta="0%"
android:duration="300"/>
</set>
7 changes: 7 additions & 0 deletions app/src/main/res/anim/mp02_up_gone.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="0%"
android:toYDelta="-100%"
android:duration="300"/>
</set>
7 changes: 7 additions & 0 deletions app/src/main/res/anim/mp02_up_visible.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="100%"
android:toYDelta="0%"
android:duration="300"/>
</set>

0 comments on commit 5d1a2c4

Please sign in to comment.