mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-08 05:24:39 +01:00
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.
This commit is contained in:
parent
42575f1380
commit
a0beecafc3
8 changed files with 61 additions and 103 deletions
|
@ -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<Long, Integer> getRowIDsAndChannels( Context context, int gameID )
|
||||
{
|
||||
Map<Long, Integer> 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;
|
||||
|
|
|
@ -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<Long, Integer> 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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<Long, Integer> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<<FORCE_CHANNEL_OFFSET)) == 0 );
|
||||
// Make sure it's big enough
|
||||
Assert.assertTrue( 0 == (~FORCE_CHANNEL_MASK & m_gi.forceChannel) );
|
||||
result |= m_gi.forceChannel << FORCE_CHANNEL_OFFSET;
|
||||
Log.d( TAG, "giflags(): adding forceChannel %d", m_gi.forceChannel );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -133,7 +133,6 @@
|
|||
<string name="key_na_sms_invite_flakey">key_na_sms_invite_flakey</string>
|
||||
<string name="key_na_dicts">key_na_dicts</string>
|
||||
<string name="key_enable_debug">key_enable_debug</string>
|
||||
<string name="key_enable_dup_invite">key_enable_dup_invite</string>
|
||||
<string name="key_enable_pending_count">key_enable_pending_count</string>
|
||||
<string name="key_enable_sms_toself">key_enable_sms_toself</string>
|
||||
<string name="key_show_fcm">key_show_fcm2</string>
|
||||
|
|
|
@ -1268,16 +1268,6 @@
|
|||
connect to the relay failed because the room named does not
|
||||
exist. (I believe this no longer occurs.) -->
|
||||
<string name="button_retry">Retry</string>
|
||||
<!-- Shown in the main screen when you launch CrossWords from an
|
||||
invitation (received in email or messaging app, say) and
|
||||
there's already a game running that matches that invitation.
|
||||
It's to prevent you from opening multiple games and getting
|
||||
confused. But some people who play together all the time use
|
||||
the same room name over and over so they'll get this warning
|
||||
and it's harmless to ignore it. -->
|
||||
<string name="dup_game_query_fmt">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?</string>
|
||||
<!-- Title of generic dialog used to display information -->
|
||||
<string name="info_title">FYI…</string>
|
||||
<!-- title of dialog allowing user to pick tiles "face up". (This
|
||||
|
@ -2277,9 +2267,7 @@
|
|||
<string name="gamel_menu_storedb">Write games to SD card</string>
|
||||
<string name="gamel_menu_loaddb">Load games from SD card</string>
|
||||
<string name="gamel_menu_writegit">Copy git info to clipboard</string>
|
||||
<string name="enable_dupes_title">Accept duplicate invites</string>
|
||||
<string name="xlations_locale">Fake locale for translation</string>
|
||||
<string name="enable_dupes_summary">Accept invitations more than once</string>
|
||||
<string name="enable_pending_count_title">Show Pending messages</string>
|
||||
<string name="enable_pending_count_summary">Show number not yet acknowledged</string>
|
||||
<string name="nag_intervals">Reminder intervals (minutes1,minutes2,…)</string>
|
||||
|
|
|
@ -392,12 +392,6 @@
|
|||
android:title="@string/nag_intervals"
|
||||
/>
|
||||
|
||||
<CheckBoxPreference android:key="@string/key_enable_dup_invite"
|
||||
android:title="@string/enable_dupes_title"
|
||||
android:summary="@string/enable_dupes_summary"
|
||||
android:defaultValue="@bool/DEBUG"
|
||||
/>
|
||||
|
||||
<CheckBoxPreference android:key="@string/key_enable_pending_count"
|
||||
android:title="@string/enable_pending_count_title"
|
||||
android:summary="@string/enable_pending_count_summary"
|
||||
|
|
Loading…
Reference in a new issue