more tweaks to wordlists: display names of those that can be updated;

click on available list shows info and offers to download; etc.
This commit is contained in:
Eric House 2014-06-18 05:59:13 -07:00
parent 03b0b041fc
commit b6d316134d
10 changed files with 134 additions and 639 deletions

View file

@ -133,12 +133,11 @@ public final class R {
public static final int dict_label=0x7f0a007a;
public static final int dict_spinner=0x7f0a002f;
public static final int dictlist_button_horizontal=0x7f0a000c;
public static final int dicts_delete=0x7f0a00ad;
public static final int dicts_deselect_all=0x7f0a00ac;
public static final int dicts_delete=0x7f0a00ac;
public static final int dicts_deselect_all=0x7f0a00ab;
public static final int dicts_download=0x7f0a00aa;
public static final int dicts_getinfo=0x7f0a00ab;
public static final int dicts_move=0x7f0a00ae;
public static final int dicts_select=0x7f0a00af;
public static final int dicts_move=0x7f0a00ad;
public static final int dicts_select=0x7f0a00ae;
public static final int divider=0x7f0a0028;
public static final int dwnld_message=0x7f0a0050;
public static final int edit=0x7f0a0076;
@ -157,30 +156,30 @@ public final class R {
public static final int game_locked_check=0x7f0a002a;
public static final int game_name=0x7f0a0046;
public static final int gamel_menu_checkmoves=0x7f0a009a;
public static final int games_game_config=0x7f0a00ba;
public static final int games_game_copy=0x7f0a00bf;
public static final int games_game_delete=0x7f0a00b9;
public static final int games_game_move=0x7f0a00bb;
public static final int games_game_new_from=0x7f0a00bd;
public static final int games_game_rename=0x7f0a00be;
public static final int games_game_reset=0x7f0a00bc;
public static final int games_group_default=0x7f0a00c3;
public static final int games_group_delete=0x7f0a00c2;
public static final int games_group_movedown=0x7f0a00c1;
public static final int games_group_moveup=0x7f0a00c0;
public static final int games_group_rename=0x7f0a00c4;
public static final int games_menu_about=0x7f0a00b6;
public static final int games_menu_checkmoves=0x7f0a00b8;
public static final int games_menu_checkupdates=0x7f0a00c5;
public static final int games_menu_dicts=0x7f0a00b4;
public static final int games_menu_email=0x7f0a00b5;
public static final int games_menu_loaddb=0x7f0a00c7;
public static final int games_menu_newgame=0x7f0a00b0;
public static final int games_menu_newgroup=0x7f0a00b1;
public static final int games_menu_prefs=0x7f0a00b2;
public static final int games_menu_rateme=0x7f0a00b3;
public static final int games_menu_resend=0x7f0a00b7;
public static final int games_menu_storedb=0x7f0a00c6;
public static final int games_game_config=0x7f0a00b9;
public static final int games_game_copy=0x7f0a00be;
public static final int games_game_delete=0x7f0a00b8;
public static final int games_game_move=0x7f0a00ba;
public static final int games_game_new_from=0x7f0a00bc;
public static final int games_game_rename=0x7f0a00bd;
public static final int games_game_reset=0x7f0a00bb;
public static final int games_group_default=0x7f0a00c2;
public static final int games_group_delete=0x7f0a00c1;
public static final int games_group_movedown=0x7f0a00c0;
public static final int games_group_moveup=0x7f0a00bf;
public static final int games_group_rename=0x7f0a00c3;
public static final int games_menu_about=0x7f0a00b5;
public static final int games_menu_checkmoves=0x7f0a00b7;
public static final int games_menu_checkupdates=0x7f0a00c4;
public static final int games_menu_dicts=0x7f0a00b3;
public static final int games_menu_email=0x7f0a00b4;
public static final int games_menu_loaddb=0x7f0a00c6;
public static final int games_menu_newgame=0x7f0a00af;
public static final int games_menu_newgroup=0x7f0a00b0;
public static final int games_menu_prefs=0x7f0a00b1;
public static final int games_menu_rateme=0x7f0a00b2;
public static final int games_menu_resend=0x7f0a00b6;
public static final int games_menu_storedb=0x7f0a00c5;
public static final int games_menu_study=0x7f0a0099;
public static final int group_done=0x7f0a008c;
public static final int group_exchange=0x7f0a009e;
@ -194,10 +193,10 @@ public final class R {
public static final int juggle_players=0x7f0a0033;
public static final int lang_separator=0x7f0a002d;
public static final int lang_spinner=0x7f0a002e;
public static final int loc_item_check=0x7f0a00c9;
public static final int loc_item_clear=0x7f0a00c8;
public static final int loc_item_copy_bless=0x7f0a00cb;
public static final int loc_item_copy_eng=0x7f0a00ca;
public static final int loc_item_check=0x7f0a00c8;
public static final int loc_item_clear=0x7f0a00c7;
public static final int loc_item_copy_bless=0x7f0a00ca;
public static final int loc_item_copy_eng=0x7f0a00c9;
public static final int loc_search_button=0x7f0a0060;
public static final int loc_search_field=0x7f0a005f;
public static final int local_label=0x7f0a005b;
@ -241,9 +240,6 @@ public final class R {
public static final int public_rooms_set=0x7f0a0039;
public static final int refresh_button=0x7f0a003b;
public static final int remote_check=0x7f0a0077;
public static final int remote_dicts_deselect_all=0x7f0a00ce;
public static final int remote_dicts_download=0x7f0a00cc;
public static final int remote_dicts_getinfo=0x7f0a00cd;
public static final int revert_all=0x7f0a0081;
public static final int revert_colors=0x7f0a0080;
public static final int robot_check=0x7f0a007b;
@ -258,11 +254,11 @@ public final class R {
public static final int send_button=0x7f0a0017;
public static final int show_remote=0x7f0a0022;
public static final int shuffle_button_horizontal=0x7f0a000a;
public static final int slmenu_clear_sel=0x7f0a00d3;
public static final int slmenu_copy_sel=0x7f0a00d2;
public static final int slmenu_deselect_all=0x7f0a00d1;
public static final int slmenu_lookup_sel=0x7f0a00cf;
public static final int slmenu_select_all=0x7f0a00d0;
public static final int slmenu_clear_sel=0x7f0a00cf;
public static final int slmenu_copy_sel=0x7f0a00ce;
public static final int slmenu_deselect_all=0x7f0a00cd;
public static final int slmenu_lookup_sel=0x7f0a00cb;
public static final int slmenu_select_all=0x7f0a00cc;
public static final int smart_robot=0x7f0a0042;
public static final int sms_disabled=0x7f0a006b;
public static final int sms_phones=0x7f0a003d;
@ -324,11 +320,10 @@ public final class R {
public static final int player_list_elem=0x7f03001e;
public static final int prefs_w_buttons=0x7f03001f;
public static final int relay_game_config=0x7f030020;
public static final int remote_dicts=0x7f030021;
public static final int rename_game=0x7f030022;
public static final int smsinviter=0x7f030023;
public static final int smsinviter_item=0x7f030024;
public static final int studylist=0x7f030025;
public static final int rename_game=0x7f030021;
public static final int smsinviter=0x7f030022;
public static final int smsinviter_item=0x7f030023;
public static final int studylist=0x7f030024;
}
public static final class menu {
public static final int board_menu=0x7f090000;
@ -337,8 +332,7 @@ public final class R {
public static final int empty=0x7f090003;
public static final int games_list_menu=0x7f090004;
public static final int loc_item_menu=0x7f090005;
public static final int remote_dicts=0x7f090006;
public static final int studylist=0x7f090007;
public static final int studylist=0x7f090006;
}
public static final class raw {
public static final int changes=0x7f050000;
@ -944,12 +938,14 @@ public final class R {
*/
public static final int dict_browse_title_fmt=0x7f0601f9;
public static final int dict_host=0x7f060079;
public static final int dict_info_fmt=0x7f0602be;
/** label for dropdown by which wordlist is chosen that this
player will use. The language the game will use (which
constrains the choice of wordlists) is substituted in for
"%1$s".
*/
public static final int dict_lang_label_fmt=0x7f0600e7;
public static final int dict_on_server=0x7f0602bf;
/** string name="invite_mime">text/plain</string
*/
public static final int dict_url=0x7f060072;
@ -2580,7 +2576,7 @@ public final class R {
feature is not yet supported on Android.)
*/
public static final int title_tile_picker=0x7f0601c1;
public static final int update_dicts=0x7f0602bc;
public static final int update_dicts_fmt=0x7f0602bc;
/** text of checkbox controlling whether there's a game timer
*/
public static final int use_timer=0x7f0600d2;

View file

@ -1,41 +0,0 @@
<?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:paddingLeft="8dp"
android:paddingRight="8dp"
>
<ListView android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawSelectorOnTop="false"
/>
<LinearLayout android:id="@android:id/empty"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical|center_horizontal"
android:layout_margin="20sp"
>
<ProgressBar android:id="@+id/progress_bar"
android:indeterminate="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="20dp"
/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/remote_empty"
android:gravity="center"
/>
</LinearLayout>
</LinearLayout>

View file

@ -8,11 +8,6 @@
android:showAsAction="ifRoom"
/>
<item android:id="@+id/dicts_getinfo"
android:title="@string/getinfo"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/dicts_deselect_all"
android:title="@string/slmenu_deselect_all"
android:icon="@drawable/clear_all__gen"

View file

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/remote_dicts_download"
android:title="@string/button_download"
android:icon="@drawable/download__gen"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/remote_dicts_getinfo"
android:title="@string/getinfo"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/remote_dicts_deselect_all"
android:title="@string/slmenu_deselect_all"
android:icon="@drawable/clear_all__gen"
android:showAsAction="ifRoom"
/>
</menu>

View file

@ -2253,10 +2253,15 @@
<string name="delete_dicts">Delete wordlist[s]</string>
<string name="show_remote">Include downloadable</string>
<string name="update_dicts">Updates are available for one or more
<string name="update_dicts_fmt">Updates are available for one or more
installed wordlists. Would you like to download the new
version[s] now?</string>
version[s] of %1$s now?</string>
<string name="progress_title">Downloading</string>
<string name="dict_info_fmt">Wordlist %1$s is available for
download.\n\nDetails:\nNumber of words: %2$d\nDownload size:
%3$dK\nNote: %4$s</string>
<string name="dict_on_server">Downloadable</string>
</resources>

View file

@ -1929,8 +1929,12 @@
<string name="getinfo">Teg ofni</string>
<string name="delete_dicts">Eteled ]s[tsildrow</string>
<string name="show_remote">Edulcni elbadaolnwod</string>
<string name="update_dicts">Setadpu era elbaliava rof eno ro erom
<string name="update_dicts_fmt">Setadpu era elbaliava rof eno ro erom
dellatsni stsildrow. Dluow uoy ekil ot daolnwod eht wen
]s[noisrev ?won</string>
]s[noisrev fo %1$s ?won</string>
<string name="progress_title">Gnidaolnwod</string>
<string name="dict_info_fmt">Tsildrow %1$s si elbaliava rof
daolnwod.\n\nSliated:\nRebmun fo sdrow: %2$d\nDaolnwod ezis:
%3$dK\nEton: %4$s</string>
<string name="dict_on_server">Elbadaolnwod</string>
</resources>

View file

@ -1929,8 +1929,12 @@
<string name="getinfo">GET INFO</string>
<string name="delete_dicts">DELETE WORDLIST[S]</string>
<string name="show_remote">INCLUDE DOWNLOADABLE</string>
<string name="update_dicts">UPDATES ARE AVAILABLE FOR ONE OR MORE
<string name="update_dicts_fmt">UPDATES ARE AVAILABLE FOR ONE OR MORE
INSTALLED WORDLISTS. WOULD YOU LIKE TO DOWNLOAD THE NEW
VERSION[S] NOW?</string>
VERSION[S] OF %1$s NOW?</string>
<string name="progress_title">DOWNLOADING</string>
<string name="dict_info_fmt">WORDLIST %1$s IS AVAILABLE FOR
DOWNLOAD.\n\nDETAILS:\nNUMBER OF WORDS: %2$d\nDOWNLOAD SIZE:
%3$dK\nNOTE: %4$s</string>
<string name="dict_on_server">DOWNLOADABLE</string>
</resources>

View file

@ -78,7 +78,7 @@ public class DictsDelegate extends ListDelegateBase
private static final int SEL_REMOTE = 1;
private ListActivity m_activity;
private HashSet<String> m_closedLangs;
private Set<String> m_closedLangs;
private DictListAdapter m_adapter;
private String[] m_langs;
@ -88,15 +88,23 @@ public class DictsDelegate extends ListDelegateBase
private Map<String, XWListItem> m_selDicts;
private String m_origTitle;
private boolean m_showRemote = false;
private HashSet<String> m_needUpdates;
private Map<String, String> m_needUpdates;
private HashMap<String, XWListItem> m_curDownloads;
// private String m_needsUpdateComment;
private String m_onServerStr;
private static class DictInfo implements Comparable {
public String m_name;
// public boolean m_needsUpdate;
public String m_lang;
public DictInfo( String name, String lang ) { m_name = name; m_lang = lang; }
public int m_nWords, m_nBytes;
public String m_note;
public DictInfo( String name, String lang, int nWords, int nBytes ) {
m_name = name;
m_lang = lang;
m_nWords = nWords;
m_nBytes = nBytes;
m_note = "This is the note";
}
public int compareTo( Object obj ) {
DictInfo other = (DictInfo)obj;
return m_name.compareTo( other.m_name );
@ -185,9 +193,9 @@ public class DictsDelegate extends ListDelegateBase
String name = info.m_name;
item.setText( name );
// if ( info.m_needsUpdate ) {
// item.setComment( m_needsUpdateComment );
// }
item.setOnClickListener( DictsDelegate.this );
item.setComment( m_onServerStr );
item.cache( info );
if ( m_selDicts.containsKey( name ) ) {
@ -417,12 +425,11 @@ public class DictsDelegate extends ListDelegateBase
protected void init( Bundle savedInstanceState )
{
m_onServerStr = getString( R.string.dict_on_server );
m_closedLangs = new HashSet<String>();
String[] closed = XWPrefs.getClosedLangs( m_activity );
if ( null != closed ) {
for ( String str : closed ) {
m_closedLangs.add( str );
}
m_closedLangs.addAll( Arrays.asList( closed ) );
}
m_locNames = getStringArray( R.array.loc_names );
@ -453,7 +460,7 @@ public class DictsDelegate extends ListDelegateBase
}
m_origTitle = getTitle();
} // onCreate
} // init
@Override
protected void onResume()
@ -477,8 +484,20 @@ public class DictsDelegate extends ListDelegateBase
switchShowingRemote( m_checkbox.isChecked() );
} else {
XWListItem item = (XWListItem)view;
DictBrowseDelegate.launch( m_activity, item.getText(),
(DictLoc)item.getCached() );
Object obj = item.getCached();
if ( obj instanceof DictLoc ) {
DictBrowseDelegate.launch( m_activity, item.getText(),
(DictLoc)obj );
} else {
DictInfo info = (DictInfo)obj;
int kBytes = (info.m_nBytes + 999) / 1000;
String msg = getString( R.string.dict_info_fmt, info.m_name,
info.m_nWords, kBytes, info.m_note );
int langCode = DictLangCache.getLangLangCode( m_activity, info.m_lang );
showConfirmThen( msg, R.string.button_download,
Action.DOWNLOAD_DICT_ACTION,
langCode, info.m_name );
}
}
}
@ -506,9 +525,6 @@ public class DictsDelegate extends ListDelegateBase
Utils.setItemVisible( menu, R.id.dicts_deselect_all,
0 < nSels[SEL_LOCAL] || 0 < nSels[SEL_REMOTE] );
Utils.setItemVisible( menu, R.id.dicts_getinfo,
1 == (nSels[SEL_LOCAL] + nSels[SEL_REMOTE] ) );
boolean allVolatile = 0 == nSels[SEL_REMOTE] && selItemsVolatile();
Utils.setItemVisible( menu, R.id.dicts_move,
allVolatile && DictUtils.haveWriteableSD() );
@ -523,9 +539,6 @@ public class DictsDelegate extends ListDelegateBase
boolean handled = true;
switch ( item.getItemId() ) {
case R.id.dicts_getinfo:
Utils.notImpl( m_activity );
break;
case R.id.dicts_delete:
deleteSelected();
break;
@ -739,11 +752,16 @@ public class DictsDelegate extends ListDelegateBase
}
break;
case DOWNLOAD_DICT_ACTION:
startActivity( (Intent)params[0] );
if ( DialogInterface.BUTTON_POSITIVE == which ) {
int lang = (Integer)params[0];
String name = (String)params[1];
DwnldDelegate.downloadDictInBack( m_activity, lang, name, this );
}
break;
case UPDATE_DICTS_ACTION:
if ( DialogInterface.BUTTON_POSITIVE == which ) {
String[] urls = m_needUpdates.toArray( new String[m_needUpdates.size()] );
String[] urls = m_needUpdates.values().
toArray( new String[m_needUpdates.size()] );
DwnldDelegate.downloadDictsInBack( m_activity, urls, this );
}
break;
@ -767,8 +785,9 @@ public class DictsDelegate extends ListDelegateBase
private void startDownload( int lang, String name )
{
Intent intent = mkDownloadIntent( m_activity, lang, name );
startActivity( intent );
DwnldDelegate.downloadDictInBack( m_activity, lang, name, this );
// Intent intent = mkDownloadIntent( m_activity, lang, name );
// startActivity( intent );
}
private void mkListAdapter()
@ -874,22 +893,21 @@ public class DictsDelegate extends ListDelegateBase
return items;
}
private static Intent mkDownloadIntent( Context context, String dict_url )
{
// private static Intent mkDownloadIntent( Context context, String dict_url )
// {
// Uri uri = Uri.parse( dict_url );
// Intent intent = new Intent( Intent.ACTION_VIEW, uri );
// intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
// return intent;
Intent intent = new Intent( context, RemoteDictsActivity.class );
return intent;
}
// }
private static Intent mkDownloadIntent( Context context,
int lang, String dict )
{
String dict_url = Utils.makeDictUrl( context, lang, dict );
return mkDownloadIntent( context, dict_url );
Assert.fail();
return null;
// String dict_url = Utils.makeDictUrl( context, lang, dict );
// return mkDownloadIntent( context, dict_url );
}
public static void launchAndDownload( Activity activity, int lang,
@ -972,11 +990,16 @@ public class DictsDelegate extends ListDelegateBase
{
boolean success = false;
JSONArray langs = null;
m_needUpdates = new HashSet<String>();
m_needUpdates = new HashMap<String, String>();
if ( null != jsonData ) {
Set<String> closedLangs = new HashSet<String>();
final Set<String> curLangs =
new HashSet<String>( Arrays.asList( m_langs ) );
// DictLangCache hits the DB hundreds of times below. Fix!
DbgUtils.logf( "Fix me I'm stupid" );
try {
// DbgUtils.logf( "data: %s", jsonData );
JSONObject obj = new JSONObject( jsonData );
langs = obj.optJSONArray( "langs" );
@ -986,6 +1009,10 @@ public class DictsDelegate extends ListDelegateBase
JSONObject langObj = langs.getJSONObject( ii );
String langName = langObj.getString( "lang" );
if ( ! curLangs.contains( langName ) ) {
closedLangs.add( langName );
}
JSONArray dicts = langObj.getJSONArray( "dicts" );
int nDicts = dicts.length();
ArrayList<DictInfo> dictNames = new ArrayList<DictInfo>();
@ -993,7 +1020,9 @@ public class DictsDelegate extends ListDelegateBase
JSONObject dict = dicts.getJSONObject( jj );
String name = dict.getString( "xwd" );
name = DictUtils.removeDictExtn( name );
DictInfo info = new DictInfo( name, langName );
int nBytes = dict.optInt( "nBytes", -1 );
int nWords = dict.optInt( "nWords", -1 );
DictInfo info = new DictInfo( name, langName, nWords, nBytes );
if ( DictLangCache.haveDict( m_activity, langName, name ) ) {
boolean matches = true;
String curSum = DictLangCache.getDictMD5Sum( m_activity, name );
@ -1010,7 +1039,7 @@ public class DictsDelegate extends ListDelegateBase
if ( !matches ) {
DbgUtils.logf( "adding %s to set needing update", name );
String url = Utils.makeDictUrl( m_activity, langName, name );
m_needUpdates.add( url );
m_needUpdates.put( name, url );
}
}
dictNames.add( info );
@ -1022,19 +1051,7 @@ public class DictsDelegate extends ListDelegateBase
}
}
// Now start out with languages expanded that have an
// installed dict.
// nLangs = m_langNames.length;
// m_expanded = new boolean[nLangs];
// for ( int ii = 0; ii < nLangs; ++ii ) {
// DictInfo[] dicts = m_langInfo.get( m_langNames[ii] );
// for ( DictInfo info : dicts ) {
// if ( null != info.m_state ) {
// m_expanded[ii] = true;
// break;
// }
// }
// }
m_closedLangs.addAll( closedLangs );
success = true;
} catch ( JSONException ex ) {
@ -1080,13 +1097,16 @@ public class DictsDelegate extends ListDelegateBase
mkListAdapter();
if ( 0 < m_needUpdates.size() ) {
showConfirmThen( R.string.update_dicts,
String[] names = m_needUpdates.keySet()
.toArray(new String[m_needUpdates.size()]);
String joined = TextUtils.join( ", ", names );
showConfirmThen( getString( R.string.update_dicts_fmt,
joined ),
R.string.button_download,
Action.UPDATE_DICTS_ACTION );
}
} else {
String msg = getString( R.string.remote_no_net );
showOKOnlyDialogThen( msg, Action.FINISH_ACTION );
showOKOnlyDialog( R.string.remote_no_net );
m_checkbox.setChecked( false );
}
stopProgress();

View file

@ -1,32 +0,0 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2014 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.os.Bundle;
public class RemoteDictsActivity extends XWListActivity {
@Override
protected void onCreate( Bundle savedState )
{
RemoteDictsDelegate dlgt = new RemoteDictsDelegate( this, savedState );
super.onCreate( savedState, dlgt );
} // onCreate
}

View file

@ -1,434 +0,0 @@
/* -*- compile-command: "find-and-ant.sh debug install"; -*- */
/*
* Copyright 2014 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.ListActivity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import org.apache.http.client.methods.HttpPost;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import junit.framework.Assert;
import org.eehouse.android.xw4.DlgDelegate.Action;
import org.eehouse.android.xw4.jni.GameSummary;
public class RemoteDictsDelegate extends ListDelegateBase
implements GroupStateListener, SelectableItem,
DwnldDelegate.DownloadFinishedListener {
private ListActivity m_activity;
private boolean[] m_expanded;
private String[] m_langNames;
private static enum DictState { AVAILABLE, INSTALLED, NEEDS_UPDATE };
private static class DictInfo implements Comparable {
public String m_name;
public DictState m_state;
public String m_lang;
public DictInfo( String name, String lang ) { m_name = name; m_lang = lang; }
public int compareTo( Object obj ) {
DictInfo other = (DictInfo)obj;
return m_name.compareTo( other.m_name );
}
}
private HashMap<String, DictInfo[]> m_langInfo;
private HashMap<String, XWListItem> m_selDicts = new HashMap<String, XWListItem>();
private String m_origTitle;
// private String m_installed;
// private String m_needsUpdate;
private HashMap<String, XWListItem> m_curDownloads;
protected RemoteDictsDelegate( ListActivity activity, Bundle savedInstanceState )
{
super( activity, savedInstanceState, R.menu.remote_dicts );
m_activity = activity;
}
protected void init( Bundle savedInstanceState )
{
// m_installed = getString( R.string.dict_installed );
// m_needsUpdate = getString( R.string.dict_needs_update );
setContentView( R.layout.remote_dicts );
JSONObject params = new JSONObject(); // empty for now
m_origTitle = getTitle();
new FetchListTask( m_activity, params ).execute();
}
@Override
public boolean onPrepareOptionsMenu( Menu menu )
{
int nSelected = m_selDicts.size();
Utils.setItemVisible( menu, R.id.remote_dicts_download,
0 < countNeedDownload() );
Utils.setItemVisible( menu, R.id.remote_dicts_deselect_all,
0 < nSelected );
Utils.setItemVisible( menu, R.id.remote_dicts_getinfo, 1 == nSelected );
return true;
}
@Override
public boolean onOptionsItemSelected( MenuItem item )
{
boolean handled = true;
switch ( item.getItemId() ) {
case R.id.remote_dicts_deselect_all:
clearSelection();
break;
case R.id.remote_dicts_download:
String[] urls = new String[countNeedDownload()];
int count = 0;
m_curDownloads = new HashMap<String, XWListItem>();
for ( Iterator<XWListItem> iter = m_selDicts.values().iterator();
iter.hasNext(); ) {
XWListItem litm = iter.next();
DictInfo info = (DictInfo)litm.getCached();
if ( null == info.m_state ||
DictState.INSTALLED != info.m_state ) {
String url = Utils.makeDictUrl( m_activity, info.m_lang,
litm.getText() );
urls[count++] = url;
m_curDownloads.put( url, litm );
}
}
DwnldDelegate.downloadDictsInBack( m_activity, urls, this );
break;
default:
handled = false;
}
return handled;
}
@Override
protected boolean onBackPressed() {
boolean handled = 0 < m_selDicts.size();
if ( handled ) {
clearSelection();
}
return handled;
}
//////////////////////////////////////////////////////////////////////
// DownloadFinishedListener interface
//////////////////////////////////////////////////////////////////////
public void downloadFinished( String name, boolean success )
{
XWListItem item = m_curDownloads.get( name );
if ( null != item ) {
if ( success ) {
DictInfo info = (DictInfo)item.getCached();
info.m_state = DictState.INSTALLED;
// item.setComment( m_installed );
}
m_curDownloads.remove( name );
}
}
//////////////////////////////////////////////////////////////////////
// GroupStateListener interface
//////////////////////////////////////////////////////////////////////
public void onGroupExpandedChanged( int groupPosition, boolean expanded )
{
m_expanded[groupPosition] = expanded;
mkListAdapter();
}
//////////////////////////////////////////////////
// SelectableItem interface
//////////////////////////////////////////////////
public void itemClicked( LongClickHandler clicked, GameSummary summary )
{
}
public void itemToggled( LongClickHandler toggled, boolean selected )
{
XWListItem item = (XWListItem)toggled;
String name = item.getText();
if ( selected ) {
m_selDicts.put( name, item );
} else {
m_selDicts.remove( name );
}
invalidateOptionsMenuIf();
setTitleBar();
}
public boolean getSelected( LongClickHandler obj )
{
XWListItem item = (XWListItem)obj;
return m_selDicts.containsKey( item.getText() );
}
//////////////////////////////////////////////////
// DlgDelegate.DlgClickNotify interface
//////////////////////////////////////////////////
@Override
public void dlgButtonClicked( Action action, int which, Object[] params )
{
Assert.assertTrue( Action.FINISH_ACTION == action );
finish();
}
private int countNeedDownload()
{
int result = 0;
for ( Iterator<XWListItem> iter = m_selDicts.values().iterator();
iter.hasNext(); ) {
XWListItem litm = iter.next();
DictInfo info = (DictInfo)litm.getCached();
if ( null == info.m_state || DictState.INSTALLED != info.m_state ) {
++result;
}
}
return result;
}
private void mkListAdapter()
{
setListAdapterKeepScroll( new RDListAdapter() );
}
private void setTitleBar()
{
int nSels = m_selDicts.size();
if ( 0 == nSels ) {
setTitle( m_origTitle );
} else {
setTitle( getString( R.string.sel_items_fmt, nSels ) );
}
}
private boolean digestData( String jsonData )
{
boolean success = false;
JSONArray langs = null;
if ( null != jsonData ) {
// DictLangCache hits the DB hundreds of times below. Fix!
DbgUtils.logf( "Fix me I'm stupid" );
try {
JSONObject obj = new JSONObject( jsonData );
langs = obj.optJSONArray( "langs" );
int nLangs = langs.length();
ArrayList<String> langNames = new ArrayList<String>();
m_langInfo = new HashMap<String, DictInfo[]>();
for ( int ii = 0; ii < nLangs; ++ii ) {
JSONObject langObj = langs.getJSONObject( ii );
String langName = langObj.getString( "lang" );
JSONArray dicts = langObj.getJSONArray( "dicts" );
int nDicts = dicts.length();
ArrayList<DictInfo> dictNames = new ArrayList<DictInfo>();
for ( int jj = 0; jj < nDicts; ++jj ) {
JSONObject dict = dicts.getJSONObject( jj );
String name = dict.getString( "xwd" );
name = DictUtils.removeDictExtn( name );
DictInfo info = new DictInfo( name, langName );
if ( DictLangCache.haveDict( m_activity, langName, name ) ) {
boolean matches = true;
String curSum = DictLangCache.getDictMD5Sum( m_activity, name );
if ( null != curSum ) {
JSONArray sums = dict.getJSONArray("md5sums");
if ( null != sums ) {
matches = false;
for ( int kk = 0; !matches && kk < sums.length(); ++kk ) {
String sum = sums.getString( kk );
matches = sum.equals( curSum );
}
}
}
info.m_state = matches? DictState.INSTALLED
: DictState.NEEDS_UPDATE;
}
dictNames.add( info );
}
if ( 0 < dictNames.size() ) {
DictInfo[] asArray = dictNames.toArray( new DictInfo[dictNames.size()] );
Arrays.sort( asArray );
m_langInfo.put( langName, asArray );
langNames.add( langName );
}
}
Collections.sort( langNames );
m_langNames = langNames.toArray( new String[langNames.size()] );
// Now start out with languages expanded that have an
// installed dict.
nLangs = m_langNames.length;
m_expanded = new boolean[nLangs];
for ( int ii = 0; ii < nLangs; ++ii ) {
DictInfo[] dicts = m_langInfo.get( m_langNames[ii] );
for ( DictInfo info : dicts ) {
if ( null != info.m_state ) {
m_expanded[ii] = true;
break;
}
}
}
success = true;
} catch ( JSONException ex ) {
DbgUtils.loge( ex );
}
}
return success;
}
private void clearSelection()
{
m_selDicts.clear();
mkListAdapter();
invalidateOptionsMenuIf();
setTitleBar();
}
private class FetchListTask extends AsyncTask<Void, Void, Boolean> {
private Context m_context;
private JSONObject m_params;
public FetchListTask( Context context, JSONObject params )
{
m_context = context;
m_params = params;
}
@Override
public Boolean doInBackground( Void... unused )
{
boolean success = false;
HttpPost post = UpdateCheckReceiver.makePost( m_context, "listDicts" );
if ( null != post ) {
String json = null;
json = UpdateCheckReceiver.runPost( post, m_params );
success = digestData( json );
}
return new Boolean( success );
}
@Override
protected void onPostExecute( Boolean success )
{
if ( success ) {
mkListAdapter();
} else {
String msg = getString( R.string.remote_no_net );
showOKOnlyDialogThen( msg, Action.FINISH_ACTION );
}
}
}
private class RDListAdapter extends XWListAdapter {
private Object[] m_listInfo;
public RDListAdapter()
{
super( 0 );
}
@Override
public int getCount()
{
if ( null == m_listInfo ) {
ArrayList<Object> alist = new ArrayList<Object>();
int nLangs = m_langNames.length;
for ( int ii = 0; ii < nLangs; ++ii ) {
alist.add( new Integer(ii) );
if ( m_expanded[ii] ) {
DictInfo[] dis = m_langInfo.get( m_langNames[ii] );
alist.addAll( Arrays.asList( dis ) );
}
}
m_listInfo = alist.toArray( new Object[alist.size()] );
}
// DbgUtils.logf( "RemoteDictsDelegate.getCount() => %d", m_listInfo.length );
return m_listInfo.length;
}
@Override
public int getViewTypeCount() { return 2; }
@Override
public View getView( final int position, View convertView, ViewGroup parent )
{
if ( null != convertView ) {
DbgUtils.logf( "RemoteDictsDelegate(position=%d, convertView=%H)",
position, convertView );
}
View result = null;
Object obj = m_listInfo[position];
if ( obj instanceof Integer ) {
int ii = (Integer)obj;
String langName = m_langNames[ii];
boolean expanded = m_expanded[ii];
result = ListGroup.make( m_activity, RemoteDictsDelegate.this,
ii, langName, expanded );
} else if ( obj instanceof DictInfo ) {
DictInfo info = (DictInfo)obj;
XWListItem item =
XWListItem.inflate( m_activity, RemoteDictsDelegate.this );
result = item;
String name = info.m_name;
item.setText( name );
// if ( null != info.m_state ) {
// String comment = null;
// switch( info.m_state ) {
// case INSTALLED:
// comment = m_installed;
// break;
// case NEEDS_UPDATE:
// comment = m_needsUpdate;
// break;
// }
// item.setComment( comment );
// }
item.cache( info );
if ( m_selDicts.containsKey( name ) ) {
m_selDicts.put( name, item );
item.setSelected( true );
}
} else {
Assert.fail();
}
Assert.assertNotNull( result );
return result;
}
}
}