Add language filter in dictionary list

Julien LepillerTue Jul 20 02:56:42+0200 2021

6414737

Add language filter in dictionary list

CHANGELOG.md

11
Changelog
22
=========
33
4+
Changes in next version
5+
-----------------------
6+
7+
Here is a list of changes that are not yet part of a release, but that will
8+
appear in next release.
9+
10+
### Features
11+
12+
* It is now possible to filter the list of dictionaries by target language.
13+
414
Changes in 0.3.2.1
515
------------------
616

app/src/main/java/eu/lepiller/nani/DictionaryActivity.java

1212
import android.util.Log;
1313
import android.view.View;
1414
import android.widget.AdapterView;
15+
import android.widget.ArrayAdapter;
1516
import android.widget.ListView;
17+
import android.widget.ScrollView;
18+
import android.widget.Spinner;
1619
1720
import com.google.android.material.snackbar.Snackbar;
1821

2427
import java.net.MalformedURLException;
2528
import java.net.URL;
2629
import java.util.ArrayList;
30+
import java.util.List;
2731
2832
import eu.lepiller.nani.dictionary.DictionariesAdapter;
2933
import eu.lepiller.nani.dictionary.DictionaryFactory;

3337
    static final int DICO_REQUEST = 1;
3438
    static final String TAG = "DICO_LIST";
3539
    DictionariesAdapter adapter;
40+
    ArrayAdapter<String> langAdapter;
3641
    ArrayList<Dictionary> dictionaries;
42+
    List<String> langs;
43+
    String selectedLanguage = "";
3744
    private SwipeRefreshLayout refresher;
3845
3946
    @Override

4148
        super.onCreate(savedInstanceState);
4249
        setContentView(R.layout.activity_dictionary);
4350
51+
        final Spinner lang_view = findViewById(R.id.lang_view);
4452
        final ListView list_view = findViewById(R.id.dictionary_view);
4553
        refresher = findViewById(R.id.dictionary_refresh_layout);
4654
47-
        dictionaries = DictionaryFactory.getDictionaries(getApplicationContext());
55+
        dictionaries = new ArrayList<>();
56+
        dictionaries.addAll(DictionaryFactory.getDictionaries(getApplicationContext()));
57+
58+
        langs = new ArrayList<>();
59+
        langs.add(getString(R.string.all_langs));
60+
        langs.addAll(DictionaryFactory.getLangs(getApplicationContext()));
61+
4862
        adapter = new DictionariesAdapter(this, dictionaries);
4963
        list_view.setAdapter(adapter);
5064
65+
        langAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, langs);
66+
        langAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
67+
        lang_view.setAdapter(langAdapter);
68+
5169
        if(dictionaries.size() == 0) {
5270
            Snackbar.make(findViewById(R.id.dictionary_view), getString(R.string.no_dico_list),
5371
                    Snackbar.LENGTH_LONG).show();

6280
                startActivityForResult(intent, DICO_REQUEST);
6381
            }
6482
        });
83+
84+
        lang_view.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
85+
            @Override
86+
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
87+
                if(position == 0)
88+
                    selectedLanguage = "";
89+
                else
90+
                    selectedLanguage = parent.getItemAtPosition(position).toString();
91+
                updateDataSet();
92+
            }
93+
94+
            @Override
95+
            public void onNothingSelected(AdapterView<?> parent) {
96+
                selectedLanguage = "";
97+
                updateDataSet();
98+
            }
99+
        });
65100
    }
66101
67102
    @Override

158193
    private void updateDataSet() {
159194
        DictionaryFactory.updatePackageList();
160195
        dictionaries.clear();
161-
        dictionaries.addAll(DictionaryFactory.getDictionaries(getApplicationContext()));
196+
        dictionaries.addAll(DictionaryFactory.getDictionaries(getApplicationContext(), selectedLanguage));
197+
        langs.clear();
198+
        langs.add(getString(R.string.all_langs));
199+
        langs.addAll(DictionaryFactory.getLangs(getApplicationContext()));
162200
        adapter.notifyDataSetChanged();
201+
        langAdapter.notifyDataSetChanged();
163202
    }
164203
165204
    @Override

app/src/main/java/eu/lepiller/nani/dictionary/Dictionary.java

2222
2323
abstract public class Dictionary {
2424
    private String name;
25-
    private String description, fullDescription;
25+
    private String description, fullDescription, lang;
2626
    private int expectedFileSize;
2727
    private int expectedEntries;
2828
    private String sha256;

3030
3131
    private Drawable drawable=null, newDrawable=null;
3232
33-
    Dictionary(String name, String description, String fullDescription, File cacheDir, int fileSize, int entries, String hash) {
33+
    Dictionary(String name, String description, String fullDescription, File cacheDir, int fileSize, int entries, String hash, String lang) {
3434
        this.name = name;
3535
        this.description = description;
3636
        this.fullDescription = fullDescription;
3737
        expectedEntries = entries;
3838
        expectedFileSize = fileSize;
3939
        sha256 = hash;
40+
        this.lang = lang;
4041
        this.file = new File(cacheDir, "/dico/" + name);
4142
        this.temporaryFile = new File(cacheDir, "/tmp/" + name);
4243
    }

5960
    String getSha256() {
6061
        return sha256;
6162
    }
63+
    String getLang() {
64+
        return lang;
65+
    }
6266
    abstract public boolean canUpdate();
6367
6468
    File getFile() {

app/src/main/java/eu/lepiller/nani/dictionary/DictionaryFactory.java

1313
import java.net.MalformedURLException;
1414
import java.net.URL;
1515
import java.util.ArrayList;
16+
import java.util.Collections;
1617
import java.util.HashMap;
1718
import java.util.List;
1819
import java.util.Locale;

6667
        return null;
6768
    }
6869
70+
    public static List<String> getLangs(Context context) {
71+
        List<String> langs = new ArrayList<>();
72+
        for(Dictionary d: getDictionaries(context)) {
73+
            if(d.getLang().compareTo("") == 0)
74+
                continue;
75+
            if(langs.contains(d.getLang()))
76+
                continue;
77+
            langs.add(d.getLang());
78+
        }
79+
        Collections.sort(langs);
80+
        return langs;
81+
    }
82+
6983
    public static void updatePackageList() {
7084
        dictionaries = new ArrayList<>();
7185
        if(listFile.exists()) {

8397
                String name = "";
8498
                int current = LIST_PARSER_NONE;
8599
                String currentLanguage = "";
100+
                String lang = "";
86101
87102
                Dictionary d;
88103
                while((line = br.readLine()) != null) {

92107
                            d = new RadicalDict(name,
93108
                                    chooseLanguage(synopsis),
94109
                                    chooseLanguage(description),
95-
                                    cacheDir, url, size, entries, sha256);
110+
                                    cacheDir, url, size, entries, sha256, lang);
96111
                            Log.d("FACTORY", "radk: " + (d.isDownloaded()? "downloaded": "not downloaded"));
97112
                        } else if (type.compareTo("jmdict") == 0) {
98113
                            d = new JMDict(name,
99114
                                    chooseLanguage(synopsis),
100115
                                    chooseLanguage(description),
101-
                                    cacheDir, url, size, entries, sha256);
116+
                                    cacheDir, url, size, entries, sha256, lang);
102117
                        } else if (type.compareTo("wadoku") == 0) {
103118
                            d = new WadokuResultDictionary(name,
104119
                                    chooseLanguage(synopsis),
105120
                                    chooseLanguage(description),
106-
                                    cacheDir, url, size, entries, sha256);
121+
                                    cacheDir, url, size, entries, sha256, lang);
107122
                        } else if (type.compareTo("jibiki") == 0) {
108123
                            d = new Jibiki(name,
109124
                                    chooseLanguage(synopsis),
110125
                                    chooseLanguage(description),
111-
                                    cacheDir, url, size, entries, sha256);
126+
                                    cacheDir, url, size, entries, sha256, lang);
112127
                        } else if (type.compareTo("wadoku_pitch") == 0) {
113128
                            d = new WadokuPitchDictionary(name,
114129
                                    chooseLanguage(synopsis),
115130
                                    chooseLanguage(description),
116-
                                    cacheDir, url, size, entries, sha256);
131+
                                    cacheDir, url, size, entries, sha256, lang);
117132
                        } else {
118133
                            continue;
119134
                        }

169184
                        url = line.substring(4);
170185
                    } else if(line.startsWith("size=")) {
171186
                        size = Integer.parseInt(line.substring(5));
187+
                    } else if(line.startsWith("lang=")) {
188+
                        lang = line.substring(5);
172189
                    } else if(line.startsWith("entries=")) {
173190
                        entries = Integer.parseInt(line.substring(8));
174191
                    }

255272
        return dictionaries;
256273
    }
257274
275+
    public static ArrayList<Dictionary> getDictionaries(Context context, String langFilter) {
276+
        if(instance == null)
277+
            instance = new DictionaryFactory(context);
278+
279+
        if(langFilter.compareTo("") == 0)
280+
            return dictionaries;
281+
282+
        ArrayList<Dictionary> dicos = new ArrayList<>();
283+
        for(Dictionary d: dictionaries) {
284+
            if(d.getLang().compareTo("") == 0 || d.getLang().compareTo(langFilter) == 0)
285+
                dicos.add(d);
286+
        }
287+
        return dicos;
288+
    }
289+
258290
    public static RadicalDict getRadicalDictionary(Context context) throws NoDictionaryException {
259291
        if(instance == null)
260292
            instance = new DictionaryFactory(context);

app/src/main/java/eu/lepiller/nani/dictionary/FileDictionary.java

4040
    private final static String TAG = "FileDictionary";
4141
4242
    FileDictionary(String name, String description, String fullDescription, File cacheDir, String url,
43-
                   int fileSize, int entries, String hash) {
44-
        super(name, description, fullDescription, cacheDir, fileSize, entries, hash);
43+
                   int fileSize, int entries, String hash, String lang) {
44+
        super(name, description, fullDescription, cacheDir, fileSize, entries, hash, lang);
4545
        mUrl = url;
4646
    }
4747

app/src/main/java/eu/lepiller/nani/dictionary/JMDict.java

55
import eu.lepiller.nani.R;
66
77
public class JMDict extends ResultDictionary {
8-
    JMDict(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) {
9-
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash);
8+
    JMDict(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash, String lang) {
9+
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang);
1010
    }
1111
1212
    @Override

app/src/main/java/eu/lepiller/nani/dictionary/Jibiki.java

55
import eu.lepiller.nani.R;
66
77
public class Jibiki extends ResultDictionary {
8-
    Jibiki(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) {
9-
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash);
8+
    Jibiki(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash, String lang) {
9+
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang);
1010
    }
1111
1212
    @Override

app/src/main/java/eu/lepiller/nani/dictionary/RadicalDict.java

9595
    }
9696
9797
    RadicalDict(String name, String description, String fullDescription, File cacheDir, String url,
98-
                int fileSize, int entries, String hash) {
99-
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash);
98+
                int fileSize, int entries, String hash, String lang) {
99+
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang);
100100
    }
101101
102102
    private static boolean contains(List<String> lst, String s) {

app/src/main/java/eu/lepiller/nani/dictionary/ResultAugmenterDictionary.java

55
import eu.lepiller.nani.result.Result;
66
77
public abstract class ResultAugmenterDictionary extends FileDictionary {
8-
    ResultAugmenterDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) {
9-
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash);
8+
    ResultAugmenterDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash, String lang) {
9+
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang);
1010
    }
1111
1212
    void augment(Result r) throws IncompatibleFormatException {

app/src/main/java/eu/lepiller/nani/dictionary/ResultDictionary.java

1616
    private Huffman kanjiHuffman, readingHuffman, meaningHuffman;
1717
1818
    ResultDictionary(String name, String description, String fullDescription, File cacheDir, String url,
19-
                     int fileSize, int entries, String hash) {
20-
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash);
19+
                     int fileSize, int entries, String hash, String lang) {
20+
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang);
2121
    }
2222
2323
    @Override

app/src/main/java/eu/lepiller/nani/dictionary/WadokuPitchDictionary.java

1818
    private Huffman huffman = null;
1919
    private long triePos;
2020
21-
    WadokuPitchDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) {
22-
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash);
21+
    WadokuPitchDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash, String lang) {
22+
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang);
2323
    }
2424
2525
    @Override

app/src/main/java/eu/lepiller/nani/dictionary/WadokuResultDictionary.java

55
import eu.lepiller.nani.R;
66
77
public class WadokuResultDictionary extends ResultDictionary {
8-
    WadokuResultDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) {
9-
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash);
8+
    WadokuResultDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash, String lang) {
9+
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang);
1010
    }
1111
1212
    @Override

app/src/main/res/layout/activity_dictionary.xml

99
    tools:showIn="@layout/activity_dictionary"
1010
    android:id="@+id/dictionary_refresh_layout">
1111
12-
    <ListView
13-
        android:id="@+id/dictionary_view"
14-
        android:layout_width="match_parent"
12+
    <LinearLayout
13+
        android:layout_width="wrap_content"
1514
        android:layout_height="wrap_content"
16-
        android:layout_marginStart="8dp"
17-
        android:layout_marginLeft="8dp"
18-
        android:layout_marginTop="32dp"
19-
        android:layout_marginEnd="8dp"
20-
        android:layout_marginRight="8dp"
21-
        android:layout_marginBottom="8dp" />
15+
        android:orientation="vertical">
16+
17+
        <Spinner
18+
            android:layout_width="match_parent"
19+
            android:layout_height="wrap_content"
20+
            android:id="@+id/lang_view"
21+
            android:layout_margin="8dp" />
22+
23+
        <ListView
24+
            android:id="@+id/dictionary_view"
25+
            android:layout_width="match_parent"
26+
            android:layout_height="wrap_content"
27+
            android:layout_marginStart="8dp"
28+
            android:layout_marginLeft="8dp"
29+
            android:layout_marginTop="32dp"
30+
            android:layout_marginEnd="8dp"
31+
            android:layout_marginRight="8dp"
32+
            android:layout_marginBottom="8dp" />
33+
    </LinearLayout>
2234
2335
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
2335=
2436=
\ No newline at end of file

app/src/main/res/values/strings.xml

7676
    <string name="dictionary_expected_size_b">File size: %sB</string>
7777
    <string name="dictionary_expected_size_kb">File size: %sKB</string>
7878
    <string name="dictionary_expected_size_mb">File size: %sMB</string>
79+
    <string name="all_langs">All languages</string>
7980
8081
    <!-- Result view -->
8182
    <string name="sense_number">%d.</string>