mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-22 07:28:16 +01:00
toward rotation-safe invite dialog
Rewrite the overly-complex invite dialog that's posted when a game opens and is missing players so that it doesn't crash after an orientation change. It's still possible to dismiss it yet have the game stay open. The goal is that a game in that state always has a dialog on top of it so you don't get confused about e.g. why you don't have tiles, but there's more work to be done there. Also added a common superclass for all my DialogFragments. It may be useful e.g. for having each DelegateBase instance able to track what dialogs it currently has up, e.g. to have a policy about how many of the same class can be live. I'm thinking here of how to prevent a robot-vs-robot game from ending with a stack of 25 move reports. (The change here is that the old activity.showDialog(int) only allowed one at a time, and some of my logic takes that for granted.)
This commit is contained in:
parent
0980bcfbe5
commit
618f9cf20a
10 changed files with 256 additions and 170 deletions
|
@ -36,7 +36,7 @@ import junit.framework.Assert;
|
|||
|
||||
import org.eehouse.android.xw4.loc.LocUtils;
|
||||
|
||||
public class AboutAlert extends DialogFragment {
|
||||
public class AboutAlert extends XWDialogFragment {
|
||||
|
||||
public static AboutAlert newInstance()
|
||||
{
|
||||
|
|
|
@ -24,10 +24,10 @@ import android.app.Activity;
|
|||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.DialogInterface.OnDismissListener;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
@ -42,6 +42,7 @@ import android.widget.EditText;
|
|||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
@ -73,6 +74,7 @@ import org.eehouse.android.xw4.jni.UtilCtxt;
|
|||
import org.eehouse.android.xw4.jni.UtilCtxtImpl;
|
||||
import org.eehouse.android.xw4.jni.XwJNI.GamePtr;
|
||||
import org.eehouse.android.xw4.jni.XwJNI;
|
||||
import org.eehouse.android.xw4.loc.LocUtils;
|
||||
|
||||
public class BoardDelegate extends DelegateBase
|
||||
implements TransportProcs.TPMsgHandler, View.OnClickListener,
|
||||
|
@ -166,7 +168,7 @@ public class BoardDelegate extends DelegateBase
|
|||
|
||||
private DBAlert.OnDismissListener m_blockingODL =
|
||||
new DBAlert.OnDismissListener() {
|
||||
public void onDismissed() {
|
||||
public void onDismissed( XWDialogFragment frag ) {
|
||||
releaseIfBlocking();
|
||||
}
|
||||
};
|
||||
|
@ -267,7 +269,7 @@ public class BoardDelegate extends DelegateBase
|
|||
}
|
||||
break;
|
||||
|
||||
case DLG_DELETED:
|
||||
case DLG_DELETED: {
|
||||
ab = ab.setTitle( R.string.query_title )
|
||||
.setMessage( R.string.msg_dev_deleted )
|
||||
.setPositiveButton( android.R.string.ok, null );
|
||||
|
@ -279,6 +281,7 @@ public class BoardDelegate extends DelegateBase
|
|||
};
|
||||
ab.setNegativeButton( R.string.button_delete, lstnr );
|
||||
dialog = ab.create();
|
||||
}
|
||||
break;
|
||||
|
||||
case QUERY_TRADE:
|
||||
|
@ -355,7 +358,6 @@ public class BoardDelegate extends DelegateBase
|
|||
}
|
||||
|
||||
dialog = ab.create();
|
||||
alert.setOnDismissListener( m_blockingODL );
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -454,9 +456,20 @@ public class BoardDelegate extends DelegateBase
|
|||
.create();
|
||||
break;
|
||||
case DLG_INVITE:
|
||||
dialog = makeAlertDialog();
|
||||
InviteAlertState state = (InviteAlertState)params[0];
|
||||
dialog = makeInviteDialog( alert, state );
|
||||
if ( null != dialog ) {
|
||||
m_inviteAlert = alert;
|
||||
alert.setOnDismissListener( new DBAlert.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismissed( XWDialogFragment frag ) {
|
||||
DbgUtils.logd( TAG, "onDismissed(%s)", frag.toString() );
|
||||
m_inviteAlert = null;
|
||||
// if ( m_nMissing > 0 ) {
|
||||
// finish();
|
||||
// }
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -472,8 +485,22 @@ public class BoardDelegate extends DelegateBase
|
|||
return dialog;
|
||||
} // makeDialog
|
||||
|
||||
private Dialog makeAlertDialog()
|
||||
private static class InviteAlertState implements Serializable {
|
||||
GameSummary summary;
|
||||
CurGameInfo gi;
|
||||
boolean relayMissing;
|
||||
CommsConnTypeSet connTypes;
|
||||
long rowid;
|
||||
int nMissing;
|
||||
}
|
||||
|
||||
private Dialog makeInviteDialog( final DBAlert alert,
|
||||
final InviteAlertState state )
|
||||
{
|
||||
Dialog dialog = null;
|
||||
final Activity activity = alert.getActivity();
|
||||
if ( null != activity ) {
|
||||
final SentInvitesInfo[] sentInfo = { null };
|
||||
String message;
|
||||
int titleID;
|
||||
boolean showInviteButton = true;
|
||||
|
@ -481,59 +508,62 @@ public class BoardDelegate extends DelegateBase
|
|||
|
||||
int buttonTxt = R.string.newgame_invite;
|
||||
|
||||
if ( m_relayMissing ) {
|
||||
if ( state.relayMissing ) {
|
||||
titleID = R.string.seeking_relay;
|
||||
// If relay is only means, don't allow at all
|
||||
boolean relayOnly = 1 >= m_connTypes.size();
|
||||
boolean relayOnly = 1 >= state.connTypes.size();
|
||||
showInviteButton = !relayOnly;
|
||||
message = getString( R.string.no_relay_conn );
|
||||
if ( NetStateCache.netAvail( m_activity )
|
||||
message = activity.getString( R.string.no_relay_conn );
|
||||
if ( NetStateCache.netAvail( activity )
|
||||
&& NetStateCache.onWifi() ) {
|
||||
message += getString( R.string.wifi_warning );
|
||||
message += LocUtils.getString( activity, R.string.wifi_warning );
|
||||
}
|
||||
if ( !relayOnly ) {
|
||||
CommsConnTypeSet without = (CommsConnTypeSet)
|
||||
m_connTypes.clone();
|
||||
state.connTypes.clone();
|
||||
without.remove( CommsConnType.COMMS_CONN_RELAY );
|
||||
message += "\n\n"
|
||||
+ getString( R.string.drop_relay_warning_fmt,
|
||||
without.toString( m_activity, true ) );
|
||||
+ LocUtils.getString( activity,
|
||||
R.string.drop_relay_warning_fmt,
|
||||
without.toString( activity, true ) );
|
||||
buttonTxt = R.string.newgame_drop_relay;
|
||||
}
|
||||
} else {
|
||||
m_sentInfo = DBUtils.getInvitesFor( m_activity, m_rowid );
|
||||
int nSent = m_sentInfo.getMinPlayerCount();
|
||||
boolean invitesSent = nSent >= m_nMissing;
|
||||
sentInfo[0] = DBUtils.getInvitesFor( activity, state.rowid );
|
||||
int nSent = sentInfo[0].getMinPlayerCount();
|
||||
boolean invitesSent = nSent >= state.nMissing;
|
||||
if ( invitesSent ) {
|
||||
if ( m_summary.hasRematchInfo() ) {
|
||||
if ( state.summary.hasRematchInfo() ) {
|
||||
titleID = R.string.waiting_rematch_title;
|
||||
message = getString( R.string.rematch_msg );
|
||||
message = LocUtils.getString( activity, R.string.rematch_msg );
|
||||
} else {
|
||||
titleID = R.string.waiting_invite_title;
|
||||
message = getQuantityString( R.plurals.invite_sent_fmt,
|
||||
nSent, nSent, m_nMissing );
|
||||
message = LocUtils
|
||||
.getQuantityString( activity, R.plurals.invite_sent_fmt,
|
||||
nSent, nSent, state.nMissing );
|
||||
}
|
||||
buttonTxt = R.string.button_reinvite;
|
||||
showNeutButton = true;
|
||||
} else if ( DeviceRole.SERVER_ISCLIENT == m_gi.serverRole ) {
|
||||
Assert.assertFalse( m_summary.hasRematchInfo() );
|
||||
message = getString( R.string.invited_msg );
|
||||
} else if ( DeviceRole.SERVER_ISCLIENT == state.gi.serverRole ) {
|
||||
Assert.assertFalse( state.summary.hasRematchInfo() );
|
||||
message = LocUtils.getString( activity, R.string.invited_msg );
|
||||
titleID = R.string.waiting_title;
|
||||
showInviteButton = false;
|
||||
} else {
|
||||
titleID = R.string.waiting_title;
|
||||
message = getQuantityString( R.plurals.invite_msg_fmt,
|
||||
m_nMissing, m_nMissing );
|
||||
message = LocUtils
|
||||
.getQuantityString( activity, R.plurals.invite_msg_fmt,
|
||||
state.nMissing, state.nMissing );
|
||||
}
|
||||
|
||||
if ( ! invitesSent && showInviteButton ) {
|
||||
String ps = null;
|
||||
if ( m_nMissing > 1 ) {
|
||||
ps = getString( R.string.invite_multiple );
|
||||
if ( state.nMissing > 1 ) {
|
||||
ps = LocUtils.getString( activity, R.string.invite_multiple );
|
||||
} else {
|
||||
boolean[] avail = NFCUtils.nfcAvail( m_activity );
|
||||
boolean[] avail = NFCUtils.nfcAvail( activity );
|
||||
if ( avail[1] ) {
|
||||
ps = getString( R.string.invite_if_nfc );
|
||||
ps = LocUtils.getString( activity, R.string.invite_if_nfc );
|
||||
}
|
||||
}
|
||||
if ( null != ps ) {
|
||||
|
@ -541,7 +571,7 @@ public class BoardDelegate extends DelegateBase
|
|||
}
|
||||
}
|
||||
|
||||
message += "\n\n" + getString( R.string.invite_stays );
|
||||
message += "\n\n" + LocUtils.getString( activity, R.string.invite_stays );
|
||||
}
|
||||
|
||||
// Button button = ad.getButton( AlertDialog.BUTTON_POSITIVE );
|
||||
|
@ -554,13 +584,13 @@ public class BoardDelegate extends DelegateBase
|
|||
|
||||
OnClickListener lstnr = new OnClickListener() {
|
||||
public void onClick( DialogInterface dialog, int item ){
|
||||
if ( !m_relayMissing ||
|
||||
! m_connTypes.contains(CommsConnType.COMMS_CONN_RELAY) ) {
|
||||
Assert.assertTrue( 0 < m_nMissing );
|
||||
if ( m_summary.hasRematchInfo() ) {
|
||||
if ( !state.relayMissing ||
|
||||
! state.connTypes.contains(CommsConnType.COMMS_CONN_RELAY) ) {
|
||||
Assert.assertTrue( 0 < state.nMissing );
|
||||
if ( state.summary.hasRematchInfo() ) {
|
||||
tryRematchInvites( true );
|
||||
} else {
|
||||
callInviteChoices( m_sentInfo );
|
||||
callInviteChoices( sentInfo[0] );
|
||||
}
|
||||
} else {
|
||||
askDropRelay();
|
||||
|
@ -582,8 +612,7 @@ public class BoardDelegate extends DelegateBase
|
|||
OnClickListener lstnrMore = new OnClickListener() {
|
||||
public void onClick( DialogInterface dialog,
|
||||
int item ) {
|
||||
String msg = m_sentInfo
|
||||
.getAsText( m_activity );
|
||||
String msg = sentInfo[0].getAsText( activity );
|
||||
makeOkOnlyBuilder( msg ).show();
|
||||
}
|
||||
};
|
||||
|
@ -599,9 +628,10 @@ public class BoardDelegate extends DelegateBase
|
|||
ab.setNegativeButton( R.string.button_wait, lstnrWait );
|
||||
}
|
||||
|
||||
Dialog dialog = ab.create();
|
||||
return dialog;
|
||||
dialog = ab.create();
|
||||
}
|
||||
return dialog;
|
||||
} // makeInviteDialog
|
||||
|
||||
public BoardDelegate( Delegator delegator, Bundle savedInstanceState )
|
||||
{
|
||||
|
@ -757,8 +787,8 @@ public class BoardDelegate extends DelegateBase
|
|||
// in case of change...
|
||||
setBackgroundColor();
|
||||
setKeepScreenOn();
|
||||
} else if ( 0 < m_nMissing ) {
|
||||
showInviteAlert();
|
||||
} else {
|
||||
showInviteAlertIf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1197,6 +1227,11 @@ public class BoardDelegate extends DelegateBase
|
|||
case DELETE_AND_EXIT:
|
||||
finish();
|
||||
break;
|
||||
|
||||
case LAUNCH_INVITE_ACTION:
|
||||
showInviteAlertIf();
|
||||
break;
|
||||
|
||||
default:
|
||||
handled = false;
|
||||
}
|
||||
|
@ -1663,7 +1698,7 @@ public class BoardDelegate extends DelegateBase
|
|||
skipDismiss = !tryRematchInvites( false );
|
||||
} else if ( !m_haveInvited ) {
|
||||
m_haveInvited = true;
|
||||
showInviteAlert();
|
||||
showInviteAlertIf();
|
||||
invalidateOptionsMenuIf();
|
||||
skipDismiss = true;
|
||||
} else {
|
||||
|
@ -1981,7 +2016,7 @@ public class BoardDelegate extends DelegateBase
|
|||
post( new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showInviteAlert();
|
||||
showInviteAlertIf();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
@ -2292,8 +2327,6 @@ public class BoardDelegate extends DelegateBase
|
|||
if ( null != m_inviteAlert ) {
|
||||
DbgUtils.logd( TAG, "dismissing invite alert" );
|
||||
m_inviteAlert.dismiss();
|
||||
m_inviteAlert = null;
|
||||
// m_showedInviteAlert = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2421,11 +2454,18 @@ public class BoardDelegate extends DelegateBase
|
|||
} );
|
||||
}
|
||||
|
||||
private void showInviteAlert()
|
||||
private void showInviteAlertIf()
|
||||
{
|
||||
if ( !m_showedInviteAlert && null == m_inviteAlert ) {
|
||||
if ( null == m_inviteAlert & m_nMissing > 0 ) {
|
||||
m_showedInviteAlert = true;
|
||||
showDialogFragment( DlgID.DLG_INVITE );
|
||||
InviteAlertState ias = new InviteAlertState();
|
||||
ias.summary = m_summary;
|
||||
ias.gi = m_gi;
|
||||
ias.relayMissing = m_relayMissing;
|
||||
ias.connTypes = m_connTypes;
|
||||
ias.rowid = m_rowid;
|
||||
ias.nMissing = m_nMissing;
|
||||
showDialogFragment( DlgID.DLG_INVITE, ias );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,19 +33,13 @@ import java.io.Serializable;
|
|||
|
||||
import junit.framework.Assert;
|
||||
|
||||
public class DBAlert extends DialogFragment {
|
||||
public class DBAlert extends XWDialogFragment {
|
||||
private static final String TAG = DBAlert.class.getSimpleName();
|
||||
private static final String DLG_ID_KEY = "DLG_ID_KEY";
|
||||
private static final String PARMS_KEY = "PARMS_KEY";
|
||||
|
||||
public interface OnDismissListener {
|
||||
void onDismissed();
|
||||
}
|
||||
|
||||
private Object[] mParams;
|
||||
private DlgID mDlgID;
|
||||
private OnDismissListener m_onDismiss;
|
||||
|
||||
public static DBAlert newInstance( DlgID dlgID, Object[] params )
|
||||
{
|
||||
if ( BuildConfig.DEBUG ) {
|
||||
|
@ -78,15 +72,6 @@ public class DBAlert extends DialogFragment {
|
|||
bundle.putSerializable( PARMS_KEY, mParams );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss( DialogInterface dif )
|
||||
{
|
||||
if ( null != m_onDismiss ) {
|
||||
m_onDismiss.onDismissed();
|
||||
}
|
||||
super.onDismiss( dif );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog( Bundle sis )
|
||||
{
|
||||
|
@ -126,8 +111,4 @@ public class DBAlert extends DialogFragment {
|
|||
return dialog;
|
||||
}
|
||||
|
||||
protected void setOnDismissListener( OnDismissListener lstnr )
|
||||
{
|
||||
m_onDismiss = lstnr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ public class DelegateBase implements DlgClickNotify,
|
|||
private Activity m_activity;
|
||||
private int m_optionsMenuID;
|
||||
private int m_layoutID;
|
||||
private boolean m_finishCalled;
|
||||
private View m_rootView;
|
||||
private boolean m_isVisible;
|
||||
private ArrayList<Runnable> m_visibleProcs = new ArrayList<Runnable>();
|
||||
|
@ -297,7 +298,10 @@ public class DelegateBase implements DlgClickNotify,
|
|||
if ( m_activity instanceof MainActivity ) {
|
||||
MainActivity main = (MainActivity)m_activity;
|
||||
if ( main.inDPMode() ) {
|
||||
if ( !m_finishCalled ) {
|
||||
m_finishCalled = true;
|
||||
main.finishFragment();
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ import org.eehouse.android.xw4.loc.LocUtils;
|
|||
/** Abstract superclass for Alerts that have moved from and are still created
|
||||
* inside DlgDelegate
|
||||
*/
|
||||
public class DlgDelegateAlert extends DialogFragment {
|
||||
public class DlgDelegateAlert extends XWDialogFragment {
|
||||
private static final String TAG = DlgDelegateAlert.class.getSimpleName();
|
||||
private static final String STATE_KEY = "STATE_KEY";
|
||||
private DlgState m_state;
|
||||
|
|
|
@ -142,6 +142,21 @@ public class DualpaneDelegate extends DelegateBase {
|
|||
return handled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDismissed( Action action, Object[] params )
|
||||
{
|
||||
boolean handled = false;
|
||||
MainActivity main = (MainActivity)m_activity;
|
||||
XWFragment[] frags = main.getVisibleFragments();
|
||||
for ( XWFragment frag : frags ) {
|
||||
handled = frag.getDelegate().onDismissed( action, params );
|
||||
if ( handled ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inviteChoiceMade( Action action, InviteMeans means,
|
||||
Object[] params )
|
||||
|
|
|
@ -212,7 +212,7 @@ public class GameConfigDelegate extends DelegateBase
|
|||
.create();
|
||||
alert.setOnDismissListener( new DBAlert.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismissed() {
|
||||
public void onDismissed( XWDialogFragment frag ) {
|
||||
if ( m_gi.forceRemoteConsistent() ) {
|
||||
showToast( R.string.forced_consistent );
|
||||
loadPlayersList();
|
||||
|
@ -251,7 +251,7 @@ public class GameConfigDelegate extends DelegateBase
|
|||
|
||||
alert.setOnDismissListener( new DBAlert.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismissed() {
|
||||
public void onDismissed( XWDialogFragment frag ) {
|
||||
closeNoSave();
|
||||
}
|
||||
} );
|
||||
|
|
|
@ -827,7 +827,7 @@ public class GamesListDelegate extends ListDelegateBase
|
|||
0, true ) );
|
||||
alert.setOnDismissListener( new DBAlert.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismissed() {
|
||||
public void onDismissed( XWDialogFragment frag ) {
|
||||
String name = etext.getText().toString();
|
||||
if ( 0 == name.length() ) {
|
||||
name = CommonPrefs.
|
||||
|
|
|
@ -30,7 +30,7 @@ import junit.framework.Assert;
|
|||
|
||||
import org.eehouse.android.xw4.loc.LocUtils;
|
||||
|
||||
public class LookupAlert extends DialogFragment {
|
||||
public class LookupAlert extends XWDialogFragment {
|
||||
private LookupAlertView m_view;
|
||||
|
||||
public static LookupAlert newInstance( String[] words, int lang, boolean noStudy )
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- compile-command: "find-and-gradle.sh insXw4Debug"; -*- */
|
||||
/*
|
||||
* Copyright 2017 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
package org.eehouse.android.xw4;
|
||||
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.content.DialogInterface;
|
||||
|
||||
class XWDialogFragment extends DialogFragment {
|
||||
private OnDismissListener m_onDismiss;
|
||||
|
||||
public interface OnDismissListener {
|
||||
void onDismissed( XWDialogFragment frag );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss( DialogInterface dif )
|
||||
{
|
||||
if ( null != m_onDismiss ) {
|
||||
m_onDismiss.onDismissed( this );
|
||||
}
|
||||
super.onDismiss( dif );
|
||||
}
|
||||
|
||||
protected void setOnDismissListener( OnDismissListener lstnr )
|
||||
{
|
||||
m_onDismiss = lstnr;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue