From a0beecafc328fdd94a5b8be545472120c0bbcd76 Mon Sep 17 00:00:00 2001 From: Eric House Date: Sat, 29 Aug 2020 16:11:24 -0700 Subject: [PATCH] Don't accept invitation again for same channel Do away with debug setting to accept duplicate invitations. Change definition of duplicate to mean specifying a channel and gameID that already exist. So now send-to-self works without a debug preference. Accidentally clicking on the same emailed invite twice will still be blocked. There will be problems if a game's been deleted but those have probably always been here. --- .../java/org/eehouse/android/xw4/DBUtils.java | 46 ++++++++--------- .../android/xw4/GamesListDelegate.java | 36 +++++++------ .../java/org/eehouse/android/xw4/XWPrefs.java | 5 -- .../eehouse/android/xw4/XWServiceHelper.java | 50 ++++--------------- .../eehouse/android/xw4/jni/GameSummary.java | 8 +++ .../app/src/main/res/values/common_rsrc.xml | 1 - .../app/src/main/res/values/strings.xml | 12 ----- .../android/app/src/main/res/xml/xwprefs.xml | 6 --- 8 files changed, 61 insertions(+), 103 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DBUtils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DBUtils.java index 470fe9d7e..7b7b4aa84 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DBUtils.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DBUtils.java @@ -826,13 +826,35 @@ public class DBUtils { } cursor.close(); } - if ( null != result && 1 < result.length ) { + if ( 1 < result.length ) { Log.i( TAG, "getRowIDsFor(%x)=>length %d array", gameID, result.length ); } return result; } + static Map getRowIDsAndChannels( Context context, int gameID ) + { + Map result = new HashMap<>(); + String[] columns = { ROW_ID, DBHelper.GIFLAGS }; + String selection = String.format( DBHelper.GAMEID + "=%d", gameID ); + initDB( context ); + synchronized( s_dbHelper ) { + Cursor cursor = query( TABLE_NAMES.SUM, columns, selection ); + while ( cursor.moveToNext() ) { + int flags = cursor.getInt( cursor.getColumnIndex( DBHelper.GIFLAGS ) ); + int forceChannel = (flags >> GameSummary.FORCE_CHANNEL_OFFSET) + & GameSummary.FORCE_CHANNEL_MASK; + long rowid = cursor.getLong( cursor.getColumnIndex( ROW_ID ) ); + result.put( rowid, forceChannel ); + // Log.i( TAG, "getRowIDsAndChannels(): added %d => %d", + // rowid, forceChannel ); + } + cursor.close(); + } + return result; + } + public static boolean haveGame( Context context, int gameID ) { long[] rows = getRowIDsFor( context, gameID ); @@ -900,28 +922,6 @@ public class DBUtils { } } - // Return creation time of newest game matching this nli, or null - // if none found. - public static Date getMostRecentCreate( Context context, int gameID ) - { - Date result = null; - - String selection = String.format("%s=%d", DBHelper.GAMEID, gameID ); - String[] columns = { DBHelper.CREATE_TIME }; - - initDB( context ); - synchronized( s_dbHelper ) { - Cursor cursor = query( TABLE_NAMES.SUM, columns, selection ); - if ( cursor.moveToNext() ) { - int indx = cursor.getColumnIndex( columns[0] ); - result = new Date( cursor.getLong( indx ) ); - } - cursor.close(); - } - - return result; - } - public static String[] getRelayIDs( Context context, long[][] rowIDs ) { String[] result = null; 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 bb372fa18..5f43758fd 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 @@ -2341,26 +2341,30 @@ public class GamesListDelegate extends ListDelegateBase boolean handled = false; Assert.assertTrue( nli.isValid() ); - Date create = null; - create = DBUtils.getMostRecentCreate( m_activity, nli.gameID() ); + Map rowids = DBUtils + .getRowIDsAndChannels( m_activity, nli.gameID() ); - if ( null == create ) { - if ( checkWarnNoDict( nli ) ) { - makeNewNetGame( nli ); - handled = true; + if ( 0 < rowids.size() ) { + // There's already a game? Better not have same channel as invite + // creates + for ( long rowid : rowids.keySet() ) { + if ( nli.forceChannel == rowids.get(rowid) ) { + // May not want this at all if it's never a bad thing + makeOkOnlyBuilder( R.string.dropped_dupe ) + .setParams(rowid) + .setTitle("add open game button") + .show(); + handled = true; + break; + } } - } else if ( XWPrefs.getSecondInviteAllowed( m_activity ) ) { - String msg = getString( R.string.dup_game_query_fmt, - create.toString() ); - m_netLaunchInfo = nli; - makeConfirmThenBuilder( msg, Action.NEW_NET_GAME ) - .setParams( nli ) - .show(); - handled = true; - } else { - makeOkOnlyBuilder( R.string.dropped_dupe ).show(); + } + + if ( !handled && checkWarnNoDict( nli ) ) { + makeNewNetGame( nli ); handled = true; } + return handled; } // startNewNetGame diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java index 3528103e2..870dd1e01 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWPrefs.java @@ -57,11 +57,6 @@ public class XWPrefs { BuildConfig.DEBUG ); } - public static boolean getSecondInviteAllowed( Context context ) - { - return getPrefsBoolean( context, R.string.key_enable_dup_invite, false ); - } - public static boolean moveCountEnabled( Context context ) { return getPrefsBoolean( context, R.string.key_enable_pending_count, diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWServiceHelper.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWServiceHelper.java index 18e7c6c1a..42a9bf6da 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWServiceHelper.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWServiceHelper.java @@ -135,48 +135,18 @@ abstract class XWServiceHelper { } else { success = true; } - CurGameInfo gi = null; + if ( success ) { - long[] rowids = DBUtils.getRowIDsFor( mContext, nli.gameID() ); - if ( 0 == rowids.length ) { - // cool: we're good - } else if ( rowids.length < nli.nPlayersT ) { - success = XWPrefs.getSecondInviteAllowed( mContext ); - - if ( BuildConfig.DEBUG && !success ) { - DbgUtils.showf( mContext, "Dropping duplicate invite" ); - } - - // Allowing a second game allows the common testing action of - // sending invitation to myself. But we still need to check - // for duplicates! forceChannel's hard to dig up, but works - for ( int ii = 0; success && ii < rowids.length; ++ii ) { - long rowid = rowids[ii]; - try ( GameLock lock = GameLock.tryLockRO( rowid ) ) { - // drop invite if can't open game; likely a dupe! - if ( null != lock ) { - gi = new CurGameInfo( mContext ); - GamePtr gamePtr = GameUtils - .loadMakeGame( mContext, gi, lock ); - gamePtr.release(); - } else { - DbgUtils.toastNoLock( TAG, mContext, rowid, - "handleInvitation()" ); - } + Map rowids = DBUtils.getRowIDsAndChannels( mContext, nli.gameID() ); + // Accept only if there isn't already a game with the channel + for ( long rowid : rowids.keySet() ) { + if ( rowids.get( rowid ) == nli.forceChannel ) { + if ( BuildConfig.DEBUG ) { + DbgUtils.showf( mContext, "Dropping duplicate invite" ); } - - if ( null == gi ) { - // locked. Maybe it's open? - try ( JNIThread thrd = JNIThread.getRetained( rowid ) ) { - if ( null != thrd ) { - gi = thrd.getGI(); - } - } - } - success = null != gi && gi.forceChannel != nli.forceChannel; + success = false; + break; } - } else { - success = false; } if ( success ) { @@ -198,7 +168,7 @@ abstract class XWServiceHelper { } } } - Log.d( TAG, "handleInvitation() => %b (gi: %s)", success, gi ); + Log.d( TAG, "handleInvitation() => %b", success ); return success; } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/GameSummary.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/GameSummary.java index 940bc2d99..14ec21c2a 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/GameSummary.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/GameSummary.java @@ -58,6 +58,8 @@ public class GameSummary implements Serializable { public static final int MSG_FLAGS_GAMEOVER = 4; public static final int MSG_FLAGS_ALL = 7; public static final int DUP_MODE_MASK = 1 << (CurGameInfo.MAX_NUM_PLAYERS * 2); + public static final int FORCE_CHANNEL_OFFSET = (CurGameInfo.MAX_NUM_PLAYERS * 2) + 1; + public static final int FORCE_CHANNEL_MASK = 0x03; public int lastMoveTime; // set by jni's server.c on move receipt public int dupTimerExpires; @@ -372,6 +374,12 @@ public class GameSummary implements Serializable { if ( m_gi.inDuplicateMode ) { result |= DUP_MODE_MASK; } + + Assert.assertTrue( (result & (FORCE_CHANNEL_MASK<key_na_sms_invite_flakey key_na_dicts key_enable_debug - key_enable_dup_invite key_enable_pending_count key_enable_sms_toself key_show_fcm2 diff --git a/xwords4/android/app/src/main/res/values/strings.xml b/xwords4/android/app/src/main/res/values/strings.xml index 7620bc9b0..698ae558e 100644 --- a/xwords4/android/app/src/main/res/values/strings.xml +++ b/xwords4/android/app/src/main/res/values/strings.xml @@ -1268,16 +1268,6 @@ connect to the relay failed because the room named does not exist. (I believe this no longer occurs.) --> Retry - - You already have a game that seems - to have been created (on %1$s) from the same invitation. Are you - sure you want to create another? FYI…