when a move is dropped for lack of dict, alert user

Better to encourage deletion so the remote player knows what's up. This
will not happen often but it has bitten me so....
This commit is contained in:
Eric House 2021-03-21 10:33:49 -07:00
parent 637c47e506
commit 1869557f12
4 changed files with 84 additions and 18 deletions

View file

@ -52,9 +52,9 @@ public enum DlgID {
, REVERT_COLORS
, SET_DEFAULT
, SHOW_SUBST
, WARN_NODICT
, WARN_NODICT_NEW
, WARN_NODICT_SUBST
, WARN_NODICT_GENERIC // the general trying-to-open case
, WARN_NODICT_INVITED // when responding to invitation
, WARN_NODICT_SUBST // when a substitution will be possible/suggested
, DLG_BADWORDS
, NOTIFY_BADWORDS
, QUERY_MOVE

View file

@ -407,8 +407,8 @@ public class GameUtils {
String[] dictNames = gi.dictNames();
DictUtils.DictPairs pairs = DictUtils.openDicts( context, dictNames );
if ( pairs.anyMissing( dictNames ) ) {
Log.w( TAG, "loadMakeGame() failing: dicts %s unavailable",
TextUtils.join( ",", dictNames ) );
postMoveDroppedForDictNotification( context, rowid, gi.gameID,
gi.dictLang );
} else {
String langName = gi.langName( context );
gamePtr = XwJNI.initFromStream( rowid, stream, gi, dictNames,
@ -1264,6 +1264,18 @@ public class GameUtils {
}
}
private static void postMoveDroppedForDictNotification( Context context, long rowid,
int gameID, int lang )
{
Intent intent = GamesListDelegate.makeGameIDIntent( context, gameID );
String langName = DictLangCache.getLangName( context, lang );
String body = LocUtils.getString( context, R.string.no_dict_for_move_fmt,
langName );
Utils.postNotification( context, intent, R.string.no_dict_for_move_title,
body, rowid );
}
public static void postInvitedNotification( Context context, int gameID,
String body, long rowid )
{

View file

@ -637,14 +637,15 @@ public class GamesListDelegate extends ListDelegateBase
DlgID dlgID = alert.getDlgID();
switch ( dlgID ) {
case WARN_NODICT:
case WARN_NODICT_NEW:
case WARN_NODICT_GENERIC:
case WARN_NODICT_INVITED:
case WARN_NODICT_SUBST: {
final long rowid = (Long)params[0];
final String missingDictName = (String)params[1];
final int missingDictLang = (Integer)params[2];
lstnr = new OnClickListener() {
@Override
public void onClick( DialogInterface dlg, int item ) {
if ( null == missingDictName ) {
DictsDelegate
@ -666,9 +667,9 @@ public class GamesListDelegate extends ListDelegateBase
DictLangCache.getLangName( m_activity, missingDictLang );
String locLang = xlateLang( langName );
String gameName = GameUtils.getName( m_activity, rowid );
if ( DlgID.WARN_NODICT == dlgID ) {
if ( DlgID.WARN_NODICT_GENERIC == dlgID ) {
message = getString( R.string.no_dict_fmt, gameName, locLang );
} else if ( DlgID.WARN_NODICT_NEW == dlgID ) {
} else if ( DlgID.WARN_NODICT_INVITED == dlgID ) {
message = getString( R.string.invite_dict_missing_body_noname_fmt,
null, missingDictName, locLang );
} else {
@ -684,13 +685,23 @@ public class GamesListDelegate extends ListDelegateBase
.setNegativeButton( R.string.button_download, lstnr )
;
if ( DlgID.WARN_NODICT_SUBST == dlgID ) {
lstnr = new OnClickListener() {
OnClickListener neuLstnr = new OnClickListener() {
@Override
public void onClick( DialogInterface dlg, int item ) {
showDialogFragment( DlgID.SHOW_SUBST, rowid,
missingDictName, missingDictLang );
}
};
ab.setNeutralButton( R.string.button_substdict, lstnr );
ab.setNeutralButton( R.string.button_substdict, neuLstnr );
} else if ( DlgID.WARN_NODICT_GENERIC == dlgID ) {
OnClickListener neuLstnr = new OnClickListener() {
@Override
public void onClick( DialogInterface dlg, int item ) {
long[] rowids = {rowid};
deleteNamedIfConfirmed( rowids, false );
}
};
ab.setNeutralButton( R.string.button_delete, neuLstnr );
}
dialog = ab.create();
}
@ -2255,7 +2266,7 @@ public class GamesListDelegate extends ListDelegateBase
}
if ( !haveDict ) {
m_netLaunchInfo = nli;
showDialogFragment( DlgID.WARN_NODICT_NEW, 0L, nli.dict, nli.lang );
showDialogFragment( DlgID.WARN_NODICT_INVITED, 0L, nli.dict, nli.lang );
}
return haveDict;
}
@ -2286,7 +2297,8 @@ public class GamesListDelegate extends ListDelegateBase
m_missingDictRowId = rowid;
m_missingDictMenuId = forMenu;
if ( 0 == DictLangCache.getLangCount( m_activity, missingDictLang ) ) {
showDialogFragment( DlgID.WARN_NODICT, rowid, missingDictName, missingDictLang );
showDialogFragment( DlgID.WARN_NODICT_GENERIC, rowid,
missingDictName, missingDictLang );
} else if ( null != missingDictName ) {
showDialogFragment( DlgID.WARN_NODICT_SUBST, rowid, missingDictName,
missingDictLang );
@ -2457,7 +2469,10 @@ public class GamesListDelegate extends ListDelegateBase
boolean handled = false;
long[] rowids = DBUtils.getRowIDsFor( m_activity, gameID );
if ( 0 < rowids.length ) {
launchGame( rowids[0] );
long rowid = rowids[0];
if ( checkWarnNoDict( rowid ) ) {
launchGame( rowid );
}
handled = true;
}
return handled;
@ -2674,16 +2689,34 @@ public class GamesListDelegate extends ListDelegateBase
}
}
private void deleteIfConfirmed( long[] rowids, boolean skipTell )
private void mkDeleteAlert( String msg, long[] rowids, boolean skipTell )
{
String msg = getQuantityString( R.plurals.confirm_seldeletes_fmt,
rowids.length, rowids.length );
makeConfirmThenBuilder( msg, Action.DELETE_GAMES )
.setPosButton( R.string.button_delete )
.setParams( rowids, skipTell )
.show();
}
private void deleteIfConfirmed( long[] rowids, boolean skipTell )
{
String msg = getQuantityString( R.plurals.confirm_seldeletes_fmt,
rowids.length, rowids.length );
mkDeleteAlert( msg, rowids, skipTell );
}
private void deleteNamedIfConfirmed( long[] rowids, boolean skipTell )
{
String[] names = new String[rowids.length];
for ( int ii = 0; ii < rowids.length; ++ii ) {
names[ii] = DBUtils.getName( m_activity, rowids[ii] );
}
String namesStr = TextUtils.join( ", ", names );
String msg = getQuantityString( R.plurals.confirm_nameddeletes_fmt,
rowids.length, namesStr );
mkDeleteAlert( msg, rowids, skipTell );
}
private void deleteGames( long[] rowids, boolean skipTell )
{
for ( long rowid : rowids ) {

View file

@ -144,6 +144,16 @@
<item quantity="other">Are you sure you want to delete
the %1$d selected games? This action cannot be undone.</item>
</plurals>
<!-- Same as above, but games are named rather than just called
"selected." This may eventually replace the above (after some
time for translation :-) -->
<plurals name="confirm_nameddeletes_fmt">
<item quantity="one">Are you sure you want to delete
the game %1$s? This action cannot be undone.</item>
<item quantity="other">Are you sure you want to delete
the games %1$s? This action cannot be undone.</item>
</plurals>
<!-- Text of confirmation dialog posted when list_item_reset menu
is selected -->
<plurals name="confirm_reset_fmt">
@ -1223,7 +1233,7 @@
takes wordlist name and language substituted in for %1$ and
%2$ -->
<string name="no_dict_fmt">Game “%1$s” requires a %2$s wordlist.
Please download one before opening.</string>
Please download one to open it.</string>
<!-- This is an alternative message presented when there's also
the option of downloading another wordlist. Game name,
wordlist name and language are substituted in. -->
@ -1937,6 +1947,17 @@
too?</string>
<string name="inform_dict_download">\u0020(You will have to download it
first.)</string>
<!-- Title of notification shown when an incoming move has been
dropped because the game requires a wordlist that isn't
available (likely deleted since the game was created.) -->
<string name="no_dict_for_move_title">Incoming move lost</string>
<!-- Body of above notification. Tapping will attempt to open the
game, causing user to see a choice between downloading the
wordlist, deleting the game, or doing nothing. -->
<string name="no_dict_for_move_fmt">Tap to download %1$s wordlist
and recover</string>
<!-- Shown in toast when relaunching after switching dicts -->
<string name="reload_new_dict_fmt">Reloading game with %1$s</string>
<!-- Title of notification shown when invitation requires a