diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java index 3f7077770..5331827ba 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BoardDelegate.java @@ -190,37 +190,6 @@ public class BoardDelegate extends DelegateBase } 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_GETDICT: { int title = (Integer)params[0]; @@ -897,7 +866,7 @@ public class BoardDelegate extends DelegateBase break; case R.id.board_menu_archive: - showArchiveNA(); + showArchiveNA( false ); break; case R.id.board_menu_trade_commit: @@ -1013,6 +982,7 @@ public class BoardDelegate extends DelegateBase @Override public boolean onPosButton( Action action, final Object[] params ) { + // Log.d( TAG, "onPosButton(%s, %s)", action, DbgUtils.toStr( params ) ); boolean handled = true; JNICmd cmd = JNICmd.CMD_NONE; switch ( action ) { @@ -1122,7 +1092,24 @@ public class BoardDelegate extends DelegateBase break; 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; case ENABLE_SMS_DO: @@ -2106,7 +2093,7 @@ public class BoardDelegate extends DelegateBase private Handler makeJNIHandler() { Handler handler = new Handler() { - public void handleMessage( Message msg ) { + public void handleMessage( final Message msg ) { switch( msg.what ) { case JNIThread.DIALOG: showDialogFragment( DlgID.DLG_OKONLY, msg.arg1, @@ -2135,8 +2122,16 @@ public class BoardDelegate extends DelegateBase break; case JNIThread.GAME_OVER: if ( m_isFirstLaunch ) { - showDialogFragment( DlgID.GAME_OVER, m_summary, msg.arg1, - (String)msg.obj ); + runOnUiThread( new Runnable() { + @Override + public void run() { + show( GameOverAlert + .newInstance( m_summary, + msg.arg1, + (String)msg.obj, + inArchiveGroup() ) ); + } + } ); } break; case JNIThread.MSGS_SENT: @@ -2648,15 +2643,16 @@ public class BoardDelegate extends DelegateBase return curGroup == archiveGroup; } - private void showArchiveNA() + private void showArchiveNA( boolean rematchAfter ) { makeNotAgainBuilder( R.string.not_again_archive, R.string.key_na_archive, Action.ARCHIVE_ACTION ) + .setParams( rematchAfter ) .show(); } - private void archiveAndClose() + private void archiveGame( boolean closeAfter ) { String archiveName = LocUtils .getString( m_activity, R.string.group_name_archive ); @@ -2666,8 +2662,10 @@ public class BoardDelegate extends DelegateBase archiveGroupID = DBUtils.addGroup( m_activity, archiveName ); } DBUtils.moveGame( m_activity, m_rowid, archiveGroupID ); - waitCloseGame( false ); - finish(); + if ( closeAfter ) { + waitCloseGame( false ); + finish(); + } } // 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() { - 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, - long rowid, GameSummary summary, - CurGameInfo gi, GamePtr jniGamePtr ) + long rowid, long groupID, + GameSummary summary, CurGameInfo gi, + GamePtr jniGamePtr ) { boolean doIt = true; String phone = null; @@ -2768,8 +2773,8 @@ public class BoardDelegate extends DelegateBase CommsConnTypeSet connTypes = summary.conTypes; String newName = summary.getRematchName( activity ); Intent intent = GamesListDelegate - .makeRematchIntent( activity, rowid, gi, connTypes, btAddr, - phone, relayID, p2pMacAddress, newName ); + .makeRematchIntent( activity, rowid, groupID, gi, connTypes, + btAddr, phone, relayID, p2pMacAddress, newName ); if ( null != intent ) { activity.startActivity( intent ); } @@ -2800,7 +2805,8 @@ public class BoardDelegate extends DelegateBase } if ( null != gamePtr ) { - doRematchIf( activity, null, rowID, summary, gi, gamePtr ); + doRematchIf( activity, null, rowID, DBUtils.GROUPID_UNSPEC, + summary, gi, gamePtr ); gamePtr.release(); } else { Log.w( TAG, "setupRematchFor(): unable to lock game" ); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DbgUtils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DbgUtils.java index 6851d6026..4acbff84a 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DbgUtils.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DbgUtils.java @@ -30,12 +30,11 @@ import android.text.format.Time; import java.util.ArrayList; import java.util.Formatter; +import java.util.List; import java.util.Set; - import org.eehouse.android.xw4.loc.LocUtils; - public class DbgUtils { private static final String TAG = DbgUtils.class.getSimpleName(); @@ -117,6 +116,17 @@ public class DbgUtils { Log.i( TAG, "cursor: %s", dump ); } + public static String toStr( Object[] params ) + { + List strs = new ArrayList<>(); + if ( null != params ) { + for ( Object obj : params ) { + strs.add( obj.toString() ); + } + } + return TextUtils.join( ", ", strs ); + } + // public static String secondsToDateStr( long seconds ) // { // return millisToDateStr( seconds * 1000 ); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java index 0922addf8..01b69ce6e 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgDelegate.java @@ -83,7 +83,9 @@ public class DlgDelegate { TRAY_PICKED, INVITE_INFO, DISABLE_DUALPANE, + ARCHIVE_SEL_ACTION, // archive was clicked ARCHIVE_ACTION, + REMATCH_ACTION, // Dict Browser FINISH_ACTION, diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgID.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgID.java index dee0e01ef..ef0cb43f1 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgID.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DlgID.java @@ -36,7 +36,6 @@ public enum DlgID { , DLG_OKONLY , ENABLE_NFC , FORCE_REMOTE - , GAME_OVER , GET_NAME , GET_NUMBER , INVITE_CHOICES_THEN diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameOverAlert.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameOverAlert.java new file mode 100644 index 000000000..4c0f1cf2f --- /dev/null +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameOverAlert.java @@ -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 ); + } + } +} diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameUtils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameUtils.java index 9aef31fa1..a664520a1 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameUtils.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GameUtils.java @@ -119,7 +119,8 @@ public class GameUtils { * basis for a new one. */ public static GameLock resetGame( Context context, GameLock lockSrc, - GameLock lockDest, boolean juggle ) + GameLock lockDest, long groupID, + boolean juggle ) { CurGameInfo gi = new CurGameInfo( context ); CommsAddrRec addr = null; @@ -148,7 +149,9 @@ public class GameUtils { } 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 ); lockDest = GameLock.tryLock( rowid ); } else { @@ -166,7 +169,7 @@ public class GameUtils { try ( GameLock lock = GameLock.lock( rowidIn, 500 ) ) { if ( null != lock ) { tellDied( context, lock, true ); - resetGame( context, lock, lock, false ); + resetGame( context, lock, lock, DBUtils.GROUPID_UNSPEC, false ); Utils.cancelNotification( context, (int)rowidIn ); success = true; @@ -251,6 +254,11 @@ public class GameUtils { } 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; GameLock lockSrc = null; @@ -264,7 +272,8 @@ public class GameUtils { if ( null != lockSrc ) { boolean juggle = CommonPrefs.getAutoJuggle( context ); - GameLock lockDest = resetGame( context, lockSrc, null, juggle ); + GameLock lockDest = resetGame( context, lockSrc, null, groupID, + juggle ); rowid = lockDest.getRowid(); lockDest.unlock(); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java index 6735fb858..0837dcb37 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/GamesListDelegate.java @@ -87,6 +87,7 @@ public class GamesListDelegate extends ListDelegateBase private static final String ROWID_EXTRA = "rowid"; private static final String GAMEID_EXTRA = "gameid"; 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_LANG_EXTRA = "rm_lang"; private static final String REMATCH_PREFS_EXTRA = "rm_prefs"; @@ -2235,12 +2236,22 @@ public class GamesListDelegate extends ListDelegateBase { if ( null != gameName && 0 < gameName.length() ) { 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 ); long newid; if ( solo ) { - newid = GameUtils.dupeGame( m_activity, srcRowID ); + newid = GameUtils.dupeGame( m_activity, srcRowID, groupID ); if ( DBUtils.ROWID_NOTFOUND != newid ) { DBUtils.setName( m_activity, newid, gameName ); } @@ -2253,12 +2264,6 @@ public class GamesListDelegate extends ListDelegateBase int lang = extras.getInt( REMATCH_LANG_EXTRA, -1 ); 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, lang, json, addrs, gameName ); DBUtils.addRematchInfo( m_activity, newid, btAddr, phone, @@ -2709,7 +2714,7 @@ public class GamesListDelegate extends ListDelegateBase } public static Intent makeRematchIntent( Context context, long rowid, - CurGameInfo gi, + long groupID, CurGameInfo gi, CommsConnTypeSet addrTypes, String btAddr, String phone, String relayID, String p2pMacAddress, @@ -2719,6 +2724,7 @@ public class GamesListDelegate extends ListDelegateBase boolean isSolo = gi.serverRole == CurGameInfo.DeviceRole.SERVER_STANDALONE; intent = makeSelfIntent( context ) .putExtra( REMATCH_ROWID_EXTRA, rowid ) + .putExtra( REMATCH_GROUPID_EXTRA, groupID ) .putExtra( REMATCH_DICT_EXTRA, gi.dictName ) .putExtra( REMATCH_IS_SOLO, isSolo ) .putExtra( REMATCH_LANG_EXTRA, gi.dictLang ) diff --git a/xwords4/android/app/src/main/res/layout/game_over.xml b/xwords4/android/app/src/main/res/layout/game_over.xml new file mode 100644 index 000000000..e7c85f1ef --- /dev/null +++ b/xwords4/android/app/src/main/res/layout/game_over.xml @@ -0,0 +1,23 @@ + + + + + + + +