Add custom GameOver alert for GameOver with Archive checkbox

I didn't like having to re-open a game to archive it after
rematching, so now there's a checkbox that lets you archive it after
either rematching OR just using OK to dismiss the alert. Also fixed
rematch of a solo game causing new game to be created in Archive
group if that's where the source game was.

squash me
This commit is contained in:
Eric House 2019-02-10 08:53:39 -08:00
parent 0ad9b0f891
commit babca4a696
8 changed files with 277 additions and 62 deletions

View file

@ -190,37 +190,6 @@ public class BoardDelegate extends DelegateBase
} }
break; break;
case GAME_OVER: {
GameSummary summary = (GameSummary)params[0];
int title = (Integer)params[1];
String msg = (String)params[2];
ab.setTitle( title )
.setMessage( msg )
.setPositiveButton( android.R.string.ok, null );
if ( rematchSupported( m_activity, true, summary ) ) {
lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg,
int whichButton ) {
doRematchIf();
}
};
ab.setNegativeButton( R.string.button_rematch, lstnr );
// If we're not already in the "archive" group, offer to move
if ( !inArchiveGroup() ) {
lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg,
int whichButton ) {
showArchiveNA();
}
};
ab.setNeutralButton( R.string.button_archive, lstnr );
}
}
dialog = ab.create();
}
break;
case DLG_USEDICT: case DLG_USEDICT:
case DLG_GETDICT: { case DLG_GETDICT: {
int title = (Integer)params[0]; int title = (Integer)params[0];
@ -897,7 +866,7 @@ public class BoardDelegate extends DelegateBase
break; break;
case R.id.board_menu_archive: case R.id.board_menu_archive:
showArchiveNA(); showArchiveNA( false );
break; break;
case R.id.board_menu_trade_commit: case R.id.board_menu_trade_commit:
@ -1013,6 +982,7 @@ public class BoardDelegate extends DelegateBase
@Override @Override
public boolean onPosButton( Action action, final Object[] params ) public boolean onPosButton( Action action, final Object[] params )
{ {
// Log.d( TAG, "onPosButton(%s, %s)", action, DbgUtils.toStr( params ) );
boolean handled = true; boolean handled = true;
JNICmd cmd = JNICmd.CMD_NONE; JNICmd cmd = JNICmd.CMD_NONE;
switch ( action ) { switch ( action ) {
@ -1122,7 +1092,24 @@ public class BoardDelegate extends DelegateBase
break; break;
case ARCHIVE_ACTION: case ARCHIVE_ACTION:
archiveAndClose(); boolean rematchAfter = params.length >= 1 && (Boolean)params[0];
long curGroup = DBUtils.getGroupForGame( m_activity, m_rowid );
archiveGame( !rematchAfter );
if ( rematchAfter ) {
doRematchIf( curGroup ); // closes game
}
break;
case REMATCH_ACTION:
if ( params.length >= 1 && (Boolean)params[0] ) {
showArchiveNA( true );
} else {
doRematchIf(); // closes game
}
break;
case ARCHIVE_SEL_ACTION:
showArchiveNA( false );
break; break;
case ENABLE_SMS_DO: case ENABLE_SMS_DO:
@ -2106,7 +2093,7 @@ public class BoardDelegate extends DelegateBase
private Handler makeJNIHandler() private Handler makeJNIHandler()
{ {
Handler handler = new Handler() { Handler handler = new Handler() {
public void handleMessage( Message msg ) { public void handleMessage( final Message msg ) {
switch( msg.what ) { switch( msg.what ) {
case JNIThread.DIALOG: case JNIThread.DIALOG:
showDialogFragment( DlgID.DLG_OKONLY, msg.arg1, showDialogFragment( DlgID.DLG_OKONLY, msg.arg1,
@ -2135,8 +2122,16 @@ public class BoardDelegate extends DelegateBase
break; break;
case JNIThread.GAME_OVER: case JNIThread.GAME_OVER:
if ( m_isFirstLaunch ) { if ( m_isFirstLaunch ) {
showDialogFragment( DlgID.GAME_OVER, m_summary, msg.arg1, runOnUiThread( new Runnable() {
(String)msg.obj ); @Override
public void run() {
show( GameOverAlert
.newInstance( m_summary,
msg.arg1,
(String)msg.obj,
inArchiveGroup() ) );
}
} );
} }
break; break;
case JNIThread.MSGS_SENT: case JNIThread.MSGS_SENT:
@ -2648,15 +2643,16 @@ public class BoardDelegate extends DelegateBase
return curGroup == archiveGroup; return curGroup == archiveGroup;
} }
private void showArchiveNA() private void showArchiveNA( boolean rematchAfter )
{ {
makeNotAgainBuilder( R.string.not_again_archive, makeNotAgainBuilder( R.string.not_again_archive,
R.string.key_na_archive, R.string.key_na_archive,
Action.ARCHIVE_ACTION ) Action.ARCHIVE_ACTION )
.setParams( rematchAfter )
.show(); .show();
} }
private void archiveAndClose() private void archiveGame( boolean closeAfter )
{ {
String archiveName = LocUtils String archiveName = LocUtils
.getString( m_activity, R.string.group_name_archive ); .getString( m_activity, R.string.group_name_archive );
@ -2666,8 +2662,10 @@ public class BoardDelegate extends DelegateBase
archiveGroupID = DBUtils.addGroup( m_activity, archiveName ); archiveGroupID = DBUtils.addGroup( m_activity, archiveName );
} }
DBUtils.moveGame( m_activity, m_rowid, archiveGroupID ); DBUtils.moveGame( m_activity, m_rowid, archiveGroupID );
waitCloseGame( false ); if ( closeAfter ) {
finish(); waitCloseGame( false );
finish();
}
} }
// For now, supported if standalone or either BT or SMS used for transport // For now, supported if standalone or either BT or SMS used for transport
@ -2719,12 +2717,19 @@ public class BoardDelegate extends DelegateBase
private void doRematchIf() private void doRematchIf()
{ {
doRematchIf( m_activity, this, m_rowid, m_summary, m_gi, m_jniGamePtr ); doRematchIf( DBUtils.GROUPID_UNSPEC );
}
private void doRematchIf( long groupID )
{
doRematchIf( m_activity, this, m_rowid, groupID, m_summary,
m_gi, m_jniGamePtr );
} }
private static void doRematchIf( Activity activity, DelegateBase dlgt, private static void doRematchIf( Activity activity, DelegateBase dlgt,
long rowid, GameSummary summary, long rowid, long groupID,
CurGameInfo gi, GamePtr jniGamePtr ) GameSummary summary, CurGameInfo gi,
GamePtr jniGamePtr )
{ {
boolean doIt = true; boolean doIt = true;
String phone = null; String phone = null;
@ -2768,8 +2773,8 @@ public class BoardDelegate extends DelegateBase
CommsConnTypeSet connTypes = summary.conTypes; CommsConnTypeSet connTypes = summary.conTypes;
String newName = summary.getRematchName( activity ); String newName = summary.getRematchName( activity );
Intent intent = GamesListDelegate Intent intent = GamesListDelegate
.makeRematchIntent( activity, rowid, gi, connTypes, btAddr, .makeRematchIntent( activity, rowid, groupID, gi, connTypes,
phone, relayID, p2pMacAddress, newName ); btAddr, phone, relayID, p2pMacAddress, newName );
if ( null != intent ) { if ( null != intent ) {
activity.startActivity( intent ); activity.startActivity( intent );
} }
@ -2800,7 +2805,8 @@ public class BoardDelegate extends DelegateBase
} }
if ( null != gamePtr ) { if ( null != gamePtr ) {
doRematchIf( activity, null, rowID, summary, gi, gamePtr ); doRematchIf( activity, null, rowID, DBUtils.GROUPID_UNSPEC,
summary, gi, gamePtr );
gamePtr.release(); gamePtr.release();
} else { } else {
Log.w( TAG, "setupRematchFor(): unable to lock game" ); Log.w( TAG, "setupRematchFor(): unable to lock game" );

View file

@ -30,12 +30,11 @@ import android.text.format.Time;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Formatter; import java.util.Formatter;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.eehouse.android.xw4.loc.LocUtils; import org.eehouse.android.xw4.loc.LocUtils;
public class DbgUtils { public class DbgUtils {
private static final String TAG = DbgUtils.class.getSimpleName(); private static final String TAG = DbgUtils.class.getSimpleName();
@ -117,6 +116,17 @@ public class DbgUtils {
Log.i( TAG, "cursor: %s", dump ); Log.i( TAG, "cursor: %s", dump );
} }
public static String toStr( Object[] params )
{
List<String> strs = new ArrayList<>();
if ( null != params ) {
for ( Object obj : params ) {
strs.add( obj.toString() );
}
}
return TextUtils.join( ", ", strs );
}
// public static String secondsToDateStr( long seconds ) // public static String secondsToDateStr( long seconds )
// { // {
// return millisToDateStr( seconds * 1000 ); // return millisToDateStr( seconds * 1000 );

View file

@ -83,7 +83,9 @@ public class DlgDelegate {
TRAY_PICKED, TRAY_PICKED,
INVITE_INFO, INVITE_INFO,
DISABLE_DUALPANE, DISABLE_DUALPANE,
ARCHIVE_SEL_ACTION, // archive was clicked
ARCHIVE_ACTION, ARCHIVE_ACTION,
REMATCH_ACTION,
// Dict Browser // Dict Browser
FINISH_ACTION, FINISH_ACTION,

View file

@ -36,7 +36,6 @@ public enum DlgID {
, DLG_OKONLY , DLG_OKONLY
, ENABLE_NFC , ENABLE_NFC
, FORCE_REMOTE , FORCE_REMOTE
, GAME_OVER
, GET_NAME , GET_NAME
, GET_NUMBER , GET_NUMBER
, INVITE_CHOICES_THEN , INVITE_CHOICES_THEN

View file

@ -0,0 +1,160 @@
/* -*- compile-command: "find-and-gradle.sh insXw4Deb"; -*- */
/*
* Copyright 2010 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.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.eehouse.android.xw4.DlgDelegate.Action;
import org.eehouse.android.xw4.jni.GameSummary;
import org.eehouse.android.xw4.loc.LocUtils;
public class GameOverAlert extends XWDialogFragment
implements DialogInterface.OnClickListener
{
private static final String TAG = GameOverAlert.class.getSimpleName();
private static final String SUMMARY = "SUMMARY";
private static final String TITLE = "TITLE";
private static final String MSG = "MSG";
private static final String IN_ARCH = "IN_ARCH";
private AlertDialog m_dialog;
private GameSummary mSummary;
private int mTitleID;
private String mMsg;
private LinearLayout m_view;
private boolean mInArchive;
private CheckBox mArchiveBox;
// private boolean mArchiveChecked;
public static GameOverAlert newInstance( GameSummary summary,
int titleID, String msg,
boolean inArchiveGroup )
{
Log.d( TAG, "newInstance(msg=%s)", msg );
GameOverAlert result = new GameOverAlert();
Bundle args = new Bundle();
args.putSerializable( SUMMARY, summary );
args.putInt( TITLE, titleID );
args.putString( MSG, msg );
args.putBoolean( IN_ARCH, inArchiveGroup );
result.setArguments( args );
Log.d( TAG, "newInstance() => %s", result );
return result;
}
public GameOverAlert() {}
@Override
public void onSaveInstanceState( Bundle bundle )
{
bundle.putSerializable( SUMMARY, mSummary );
bundle.putInt( TITLE, mTitleID );
bundle.putString( MSG, mMsg );
bundle.putBoolean( IN_ARCH, mInArchive );
super.onSaveInstanceState( bundle );
}
@Override
public Dialog onCreateDialog( Bundle sis )
{
Log.d( TAG, "onCreateDialog()" );
if ( null == sis ) {
sis = getArguments();
}
mSummary = (GameSummary)sis.getSerializable( SUMMARY );
mTitleID = sis.getInt( TITLE );
mMsg = sis.getString( MSG );
mInArchive = sis.getBoolean( IN_ARCH );
Activity activity = getActivity();
m_view = (LinearLayout)LocUtils.inflate( activity, R.layout.game_over );
initView();
AlertDialog.Builder ab = LocUtils.makeAlertBuilder( activity )
.setTitle( mTitleID )
.setView( m_view )
.setPositiveButton( android.R.string.ok, this )
.setNeutralButton( R.string.button_rematch, this )
;
m_dialog = ab.create();
Log.d( TAG, "onCreateDialog() => %s", m_dialog );
return m_dialog;
}
@Override
protected String getFragTag() { return TAG; }
// @Override
// public void onCheckedChanged( CompoundButton buttonView, boolean isChecked )
// {
// Log.d( TAG, "onCheckedChanged(%b)", isChecked );
// mArchiveChecked = isChecked;
// }
@Override
public void onClick( DialogInterface dialog, int which )
{
Action action = null;
boolean archiveAfter =
((CheckBox)m_view.findViewById(R.id.archive_check))
.isChecked();
if ( which == AlertDialog.BUTTON_NEUTRAL ) {
action = Action.REMATCH_ACTION;
} else if ( which == AlertDialog.BUTTON_POSITIVE && archiveAfter ) {
action = Action.ARCHIVE_SEL_ACTION;
}
if ( null != action ) {
Activity activity = getActivity();
if ( activity instanceof DlgDelegate.DlgClickNotify ) {
DlgDelegate.DlgClickNotify notify
= (DlgDelegate.DlgClickNotify)activity;
notify.onPosButton( action, archiveAfter );
}
}
}
// private void trySend( Action action, boolean bool )
// {
// Log.d( TAG, "trySend(%s)", action );
// }
private void initView()
{
((TextView)m_view.findViewById( R.id.msg )).setText( mMsg );
mArchiveBox = (CheckBox)m_view.findViewById( R.id.archive_check );
if ( mInArchive ) {
mArchiveBox.setVisibility( View.GONE );
}
}
}

View file

@ -119,7 +119,8 @@ public class GameUtils {
* basis for a new one. * basis for a new one.
*/ */
public static GameLock resetGame( Context context, GameLock lockSrc, public static GameLock resetGame( Context context, GameLock lockSrc,
GameLock lockDest, boolean juggle ) GameLock lockDest, long groupID,
boolean juggle )
{ {
CurGameInfo gi = new CurGameInfo( context ); CurGameInfo gi = new CurGameInfo( context );
CommsAddrRec addr = null; CommsAddrRec addr = null;
@ -148,7 +149,9 @@ public class GameUtils {
} }
if ( null == lockDest ) { if ( null == lockDest ) {
long groupID = DBUtils.getGroupForGame( context, lockSrc.getRowid() ); if ( DBUtils.GROUPID_UNSPEC == groupID ) {
groupID = DBUtils.getGroupForGame( context, lockSrc.getRowid() );
}
long rowid = saveNewGame( context, gamePtr, gi, groupID ); long rowid = saveNewGame( context, gamePtr, gi, groupID );
lockDest = GameLock.tryLock( rowid ); lockDest = GameLock.tryLock( rowid );
} else { } else {
@ -166,7 +169,7 @@ public class GameUtils {
try ( GameLock lock = GameLock.lock( rowidIn, 500 ) ) { try ( GameLock lock = GameLock.lock( rowidIn, 500 ) ) {
if ( null != lock ) { if ( null != lock ) {
tellDied( context, lock, true ); tellDied( context, lock, true );
resetGame( context, lock, lock, false ); resetGame( context, lock, lock, DBUtils.GROUPID_UNSPEC, false );
Utils.cancelNotification( context, (int)rowidIn ); Utils.cancelNotification( context, (int)rowidIn );
success = true; success = true;
@ -251,6 +254,11 @@ public class GameUtils {
} }
public static long dupeGame( Context context, long rowidIn ) public static long dupeGame( Context context, long rowidIn )
{
return dupeGame( context, rowidIn, DBUtils.GROUPID_UNSPEC );
}
public static long dupeGame( Context context, long rowidIn, long groupID )
{ {
long rowid = DBUtils.ROWID_NOTFOUND; long rowid = DBUtils.ROWID_NOTFOUND;
GameLock lockSrc = null; GameLock lockSrc = null;
@ -264,7 +272,8 @@ public class GameUtils {
if ( null != lockSrc ) { if ( null != lockSrc ) {
boolean juggle = CommonPrefs.getAutoJuggle( context ); boolean juggle = CommonPrefs.getAutoJuggle( context );
GameLock lockDest = resetGame( context, lockSrc, null, juggle ); GameLock lockDest = resetGame( context, lockSrc, null, groupID,
juggle );
rowid = lockDest.getRowid(); rowid = lockDest.getRowid();
lockDest.unlock(); lockDest.unlock();

View file

@ -87,6 +87,7 @@ public class GamesListDelegate extends ListDelegateBase
private static final String ROWID_EXTRA = "rowid"; private static final String ROWID_EXTRA = "rowid";
private static final String GAMEID_EXTRA = "gameid"; private static final String GAMEID_EXTRA = "gameid";
private static final String REMATCH_ROWID_EXTRA = "rm_rowid"; private static final String REMATCH_ROWID_EXTRA = "rm_rowid";
private static final String REMATCH_GROUPID_EXTRA = "rm_groupid";
private static final String REMATCH_DICT_EXTRA = "rm_dict"; private static final String REMATCH_DICT_EXTRA = "rm_dict";
private static final String REMATCH_LANG_EXTRA = "rm_lang"; private static final String REMATCH_LANG_EXTRA = "rm_lang";
private static final String REMATCH_PREFS_EXTRA = "rm_prefs"; private static final String REMATCH_PREFS_EXTRA = "rm_prefs";
@ -2235,12 +2236,22 @@ public class GamesListDelegate extends ListDelegateBase
{ {
if ( null != gameName && 0 < gameName.length() ) { if ( null != gameName && 0 < gameName.length() ) {
Bundle extras = m_rematchExtras; Bundle extras = m_rematchExtras;
long srcRowID = extras.getLong( REMATCH_ROWID_EXTRA, DBUtils.ROWID_NOTFOUND ); long srcRowID = extras.getLong( REMATCH_ROWID_EXTRA,
DBUtils.ROWID_NOTFOUND );
long groupID = extras.getLong( REMATCH_GROUPID_EXTRA,
DBUtils.GROUPID_UNSPEC );
if ( DBUtils.GROUPID_UNSPEC == groupID ) {
groupID = DBUtils.getGroupForGame( m_activity, srcRowID );
}
// Don't save rematch in Archive group
if ( groupID == DBUtils.getArchiveGroup( m_activity ) ) {
groupID = XWPrefs.getDefaultNewGameGroup( m_activity );
}
boolean solo = extras.getBoolean( REMATCH_IS_SOLO, true ); boolean solo = extras.getBoolean( REMATCH_IS_SOLO, true );
long newid; long newid;
if ( solo ) { if ( solo ) {
newid = GameUtils.dupeGame( m_activity, srcRowID ); newid = GameUtils.dupeGame( m_activity, srcRowID, groupID );
if ( DBUtils.ROWID_NOTFOUND != newid ) { if ( DBUtils.ROWID_NOTFOUND != newid ) {
DBUtils.setName( m_activity, newid, gameName ); DBUtils.setName( m_activity, newid, gameName );
} }
@ -2253,12 +2264,6 @@ public class GamesListDelegate extends ListDelegateBase
int lang = extras.getInt( REMATCH_LANG_EXTRA, -1 ); int lang = extras.getInt( REMATCH_LANG_EXTRA, -1 );
String json = extras.getString( REMATCH_PREFS_EXTRA ); String json = extras.getString( REMATCH_PREFS_EXTRA );
// Don't save rematch in Archive group
long groupID = DBUtils.getGroupForGame( m_activity, srcRowID );
if ( groupID == DBUtils.getArchiveGroup( m_activity ) ) {
groupID = XWPrefs.getDefaultNewGameGroup( m_activity );
}
newid = GameUtils.makeNewMultiGame( m_activity, groupID, dict, newid = GameUtils.makeNewMultiGame( m_activity, groupID, dict,
lang, json, addrs, gameName ); lang, json, addrs, gameName );
DBUtils.addRematchInfo( m_activity, newid, btAddr, phone, DBUtils.addRematchInfo( m_activity, newid, btAddr, phone,
@ -2709,7 +2714,7 @@ public class GamesListDelegate extends ListDelegateBase
} }
public static Intent makeRematchIntent( Context context, long rowid, public static Intent makeRematchIntent( Context context, long rowid,
CurGameInfo gi, long groupID, CurGameInfo gi,
CommsConnTypeSet addrTypes, CommsConnTypeSet addrTypes,
String btAddr, String phone, String btAddr, String phone,
String relayID, String p2pMacAddress, String relayID, String p2pMacAddress,
@ -2719,6 +2724,7 @@ public class GamesListDelegate extends ListDelegateBase
boolean isSolo = gi.serverRole == CurGameInfo.DeviceRole.SERVER_STANDALONE; boolean isSolo = gi.serverRole == CurGameInfo.DeviceRole.SERVER_STANDALONE;
intent = makeSelfIntent( context ) intent = makeSelfIntent( context )
.putExtra( REMATCH_ROWID_EXTRA, rowid ) .putExtra( REMATCH_ROWID_EXTRA, rowid )
.putExtra( REMATCH_GROUPID_EXTRA, groupID )
.putExtra( REMATCH_DICT_EXTRA, gi.dictName ) .putExtra( REMATCH_DICT_EXTRA, gi.dictName )
.putExtra( REMATCH_IS_SOLO, isSolo ) .putExtra( REMATCH_IS_SOLO, isSolo )
.putExtra( REMATCH_LANG_EXTRA, gi.dictLang ) .putExtra( REMATCH_LANG_EXTRA, gi.dictLang )

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
>
<TextView android:id="@+id/msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<!-- spacer -->
<View android:layout_height="15dp"
android:layout_width="match_parent"
/>
<CheckBox android:id="@+id/archive_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_archive"
/>
</LinearLayout>