diff options
| author | Jules Aguillon | 2026-02-02 00:20:00 +0100 |
|---|---|---|
| committer | GitHub | 2026-02-02 00:20:00 +0100 |
| commit | 77c4a27c4c37b3620defcab94ffd1b2f536c88cb (patch) | |
| tree | 1bf2c5b723e1f86b0904257e7e57f4fda15378e9 /srcs/juloo.keyboard2/dict/Dictionaries.java | |
| parent | 2ecf93d9904544ee73159e9f0ee74b49057bca6c (diff) | |
| download | unexpected-keyboard-77c4a27c4c37b3620defcab94ffd1b2f536c88cb.tar.gz unexpected-keyboard-77c4a27c4c37b3620defcab94ffd1b2f536c88cb.zip | |
Spell checking (#1137)
This adds dictionary-based spell checking to the keyboard. The keyboard looks at the word being typed and matches it against a dictionary to either complete the rest of the word or find alternative spellings.
The core of this feature is implemented in cdict, which is included as a
submodule in vendor/cidct.
Cdict is developped at https://github.com/Julow/cdict
The dictionaries are hosted at https://github.com/Julow/Unexpected-Keyboard-dictionaries/
The wordlists used to build the dictionaries are the same ones used by
HeliBoard from https://codeberg.org/Helium314/aosp-dictionaries
- Add an activity accessible from the launcher app that lists available
dictionaries with a download button.
The DictionaryListView view shows the list of available dictionaries and
handles downloading and installing them.
- The Dictionaries class manages installed dictionaries. Dictionaries are
installed as individual files into the app's private directory.
- Available dictionaries are listed in dictionaries.xml, which is generated
when building Unexpected-Keyboard-dictionaries.
method.xml mentions the dictionary name for each locales.
Diffstat (limited to 'srcs/juloo.keyboard2/dict/Dictionaries.java')
| -rw-r--r-- | srcs/juloo.keyboard2/dict/Dictionaries.java | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/srcs/juloo.keyboard2/dict/Dictionaries.java b/srcs/juloo.keyboard2/dict/Dictionaries.java new file mode 100644 index 0000000..ac43c9b --- /dev/null +++ b/srcs/juloo.keyboard2/dict/Dictionaries.java @@ -0,0 +1,149 @@ +package juloo.keyboard2.dict; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Resources; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import juloo.cdict.Cdict; +import juloo.keyboard2.Logs; +import juloo.keyboard2.Utils; + +/** Manage and load installed dictionaries. */ +public final class Dictionaries +{ + public static Dictionaries instance(Context ctx) + { + if (_instance == null) + _instance = new Dictionaries(ctx); + return _instance; + } + + /** Util for finding a dictionary by name. Returns [null] if not found. */ + public static Cdict find_by_name(Cdict[] dicts, String name) + { + for (Cdict d : dicts) + if (d.name.equals(name)) + return d; + return null; + } + + /** Load an installed dictionary. Return [null] if the requested dictionary + is not installed or the dictionary couldn't be loaded. */ + public Cdict[] load(String dict_name) + { + if (_loaded_dictionaries.containsKey(dict_name)) + return _loaded_dictionaries.get(dict_name); + Cdict[] dict = load_uncached(dict_name); + _loaded_dictionaries.put(dict_name, dict); + return dict; + } + + public Set<String> get_installed() { return _installed_dictionaries; } + + public void install(String dict_name, byte[] data) throws IOException + { + FileOutputStream outp = _context.openFileOutput(dict_file_name(dict_name), + Context.MODE_PRIVATE); + outp.write(data); + outp.close(); + set_installed(dict_name); + } + + /** Return the absolute path used to store the dictionary with the given + name. Return the same result whether the dictionary is installed or not. */ + public File get_install_location(String dict_name) + { + return _context.getFileStreamPath(dict_file_name(dict_name)); + } + + /** Declare a dictionary as installed. A dictionary file must exist at the + path returned by [get_install_location(dict_name)]. */ + public void set_installed(String dict_name) + { + _installed_dictionaries.add(dict_name); + _loaded_dictionaries.remove(dict_name); + save(); + } + + public void uninstall(String dict_name) + { + _context.deleteFile(dict_file_name(dict_name)); + _installed_dictionaries.remove(dict_name); + _loaded_dictionaries.remove(dict_name); + save(); + } + + /** Private */ + + Context _context; + Set<String> _installed_dictionaries; + /** Might be 'null' when safe storage is not available. */ + SharedPreferences _shared_prefs; + Map<String, Cdict[]> _loaded_dictionaries; + + static Dictionaries _instance = null; + + static final String PREF_INSTALLED_DICTS = "installed"; + + Dictionaries(Context ctx) + { + _context = ctx; + _installed_dictionaries = new HashSet(); + _loaded_dictionaries = new TreeMap<String, Cdict[]>(); + load_prefs(); + } + + void load_prefs() + { + _shared_prefs = null; + try + { + _shared_prefs = + _context.getSharedPreferences("dictionaries", Context.MODE_PRIVATE); + Set<String> s = _shared_prefs.getStringSet(PREF_INSTALLED_DICTS, null); + if (s != null) + _installed_dictionaries.addAll(s); + } + catch (Exception e) + { + Logs.exn("", e); + } + } + + Cdict[] load_uncached(String dict_name) + { + if (!_installed_dictionaries.contains(dict_name)) + return null; + try + { + FileInputStream inp = _context.openFileInput(dict_file_name(dict_name)); + byte[] data = Utils.read_all_bytes(inp); + inp.close(); + return Cdict.of_bytes(data); + } + catch (IOException e) { return null; } + catch (Cdict.ConstructionError e) { return null; } + } + + void save() + { + if (_shared_prefs == null) + return; + _shared_prefs.edit() + .putStringSet(PREF_INSTALLED_DICTS, _installed_dictionaries) + .commit(); + } + + static String dict_file_name(String dict_name) + { + return dict_name + ".dict"; + } +} |
