diff --git a/android/KMAPro/kMAPro/src/main/AndroidManifest.xml b/android/KMAPro/kMAPro/src/main/AndroidManifest.xml index 49d7fdac07..83aad3d6d9 100644 --- a/android/KMAPro/kMAPro/src/main/AndroidManifest.xml +++ b/android/KMAPro/kMAPro/src/main/AndroidManifest.xml @@ -226,6 +226,18 @@ android:parentActivityName=".KeymanSettingsActivity" android:launchMode="singleTask" android:theme="@style/AppTheme.Base" /> + + KeymanInstallActivity --> SelectPackageActivity --> SelectLanguageActivity + * Displays a list of available languages for the user to add for a given installed packageID/keyboardID. + */ +public final class SelectLanguageActivity extends AppCompatActivity { + private static final String TAG = "SelectLanguageActivity"; + private static ArrayList> list = null; + private static KMListAdapter adapter = null; + private static Typeface titleFont = null; + private static final String titleKey = "title"; + private static final String subtitleKey = "subtitle"; + private static final String iconKey = "icon"; + private static final String isEnabledKey = "isEnabled"; + private static Context context; + private static final boolean excludeInstalledLanguages = false; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + supportRequestWindowFeature(Window.FEATURE_NO_TITLE); + context = this; + + setContentView(R.layout.activity_list_layout); + final Toolbar toolbar = findViewById(R.id.list_toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + getSupportActionBar().setDisplayShowTitleEnabled(false); + + final ListView listView = findViewById(R.id.listView); + listView.setFastScrollEnabled(true); + + final Keyboard keyboard = (Keyboard)getIntent().getSerializableExtra("keyboard"); + final String packageID = keyboard.getPackageID(); + final String keyboardID = keyboard.getKeyboardID(); + final String keyboardName = keyboard.getKeyboardName(); + String title_install = String.format(getString(R.string.title_select_language_for_package), keyboardName); + String title_no_install = getString(R.string.all_languages_installed); + final TextView textView = findViewById(R.id.bar_title); + textView.setText(title_no_install); + if (titleFont != null) { + textView.setTypeface(titleFont, Typeface.BOLD); + } + + // Get the list of available Keyboards from kmp.json + File resourceRoot = new File(context.getDir("data", Context.MODE_PRIVATE).toString() + File.separator); + PackageProcessor kmpProcessor = new PackageProcessor(resourceRoot); + List availableKeyboardsList = kmpProcessor.getKeyboardList( + packageID, keyboardID, excludeInstalledLanguages); + + final String noIcon = "0"; + list = new ArrayList>(); + for (Keyboard k : availableKeyboardsList) { + HashMap hashMap = new HashMap<>(); + hashMap.put(titleKey, k.getLanguageName()); + hashMap.put(subtitleKey, k.getLanguageID()); + String enable = "true"; + String icon = String.valueOf(R.drawable.ic_arrow_forward); + if (!excludeInstalledLanguages && KeyboardController.getInstance().keyboardExists( + k.getPackageID(), k.getKeyboardID(), k.getLanguageID())) { + icon = String.valueOf(R.drawable.ic_check); + enable = "false"; + } else { + // Update title + textView.setText(title_install); + } + hashMap.put(iconKey, icon); + hashMap.put(isEnabledKey, enable); + list.add(hashMap); + } + + String[] from = new String[]{titleKey, subtitleKey, iconKey}; + int[] to = new int[]{R.id.text1, R.id.text2, com.tavultesoft.kmea.R.id.image1}; + + adapter = new KMListAdapter(context, list, R.layout.list_row_layout2, from, to); + listView.setAdapter(adapter); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + HashMap hashMap = (HashMap) parent.getItemAtPosition(position); + Keyboard k = availableKeyboardsList.get(position); + KMManager.addKeyboard(context, k); + String confirmation = String.format(getString(R.string.added_language_to_keyboard), + k.getLanguageName(), k.getKeyboardName()); + Toast.makeText(context, confirmation, Toast.LENGTH_LONG).show(); + finish(); + } + }); + } + + @Override + public boolean onSupportNavigateUp() { + super.onBackPressed(); + return true; + } +} diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java new file mode 100644 index 0000000000..cf25028dae --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/SelectPackageActivity.java @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2020 SIL International. All rights reserved. + */ + +package com.tavultesoft.kmapro; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.TextView; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; + +import com.tavultesoft.kmea.data.Keyboard; +import com.tavultesoft.kmea.data.KeyboardController; +import com.tavultesoft.kmea.util.KMLog; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * Keyman Settings --> KeymanInstallActivity --> SelectPackageActivity + * Displays a list of installed package ID / keyboard IDs so the user can select a language from the kmp.json + */ +public final class SelectPackageActivity extends AppCompatActivity { + private static final String TAG = "SelectPackageActivity"; + private static ArrayList> list = null; + private static Typeface titleFont = null; + private static final String titleKey = "title"; + private static final String subtitleKey = "subtitle"; + private static final String iconKey = "icon"; + private static Context context; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + supportRequestWindowFeature(Window.FEATURE_NO_TITLE); + context = this; + + setContentView(R.layout.activity_list_layout); + final Toolbar toolbar = findViewById(R.id.list_toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + getSupportActionBar().setDisplayShowTitleEnabled(false); + + final ListView listView = findViewById(R.id.listView); + listView.setFastScrollEnabled(true); + + Bundle bundle = getIntent().getExtras(); + + final TextView textView = findViewById(R.id.bar_title); + textView.setText(getString(R.string.title_select_keyboard_package_list)); + if (titleFont != null) { + textView.setTypeface(titleFont, Typeface.BOLD); + } + + List packagesList = KeyboardController.getInstance().getInstalledPackagesList(); + if (packagesList == null) { + // Should never actually happen + KMLog.LogError(TAG, "Installed keyboard package list is empty"); + finish(); + } + + list = new ArrayList>(); + for (Keyboard k : packagesList) { + String keyboardName = k.getKeyboardName(); + String pkgID = k.getPackageID(); + final String noIcon = "0"; + HashMap hashMap = new HashMap<>(); + hashMap.put(titleKey, keyboardName); + hashMap.put(subtitleKey, pkgID); + String icon = String.valueOf(R.drawable.ic_arrow_forward); + hashMap.put(iconKey, icon); + list.add(hashMap); + } + + String[] from = new String[]{titleKey, subtitleKey, iconKey}; + int[] to = new int[]{com.tavultesoft.kmea.R.id.text1, com.tavultesoft.kmea.R.id.text2, com.tavultesoft.kmea.R.id.image1}; + + ListAdapter adapter = new SimpleAdapter(context, list, com.tavultesoft.kmea.R.layout.list_row_layout2, from, to) { + }; + listView.setAdapter(adapter); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + HashMap hashMap = (HashMap) parent.getItemAtPosition(position); + Bundle bundle = new Bundle(); + bundle.putSerializable("keyboard", packagesList.get(position)); + Intent intent = new Intent(context, SelectLanguageActivity.class); + intent.putExtras(bundle); + context.startActivity(intent); + } + }); + } + + @Override + public boolean onSupportNavigateUp() { + super.onBackPressed(); + return true; + } +} diff --git a/android/KMAPro/kMAPro/src/main/res/values/strings.xml b/android/KMAPro/kMAPro/src/main/res/values/strings.xml index 910e2efd18..6cc1c176ca 100644 --- a/android/KMAPro/kMAPro/src/main/res/values/strings.xml +++ b/android/KMAPro/kMAPro/src/main/res/values/strings.xml @@ -58,6 +58,12 @@ Add language to installed keyboard (from keyboard package) + + Select Keyboard Package + Select language for %1$s + Added language %1$s to %2$s + All languages already installed + Search or type URL Bookmarks diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/KeyboardController.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/KeyboardController.java index d5dfffd904..2e7c3c0eaa 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/KeyboardController.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/data/KeyboardController.java @@ -122,6 +122,37 @@ public class KeyboardController { } } + /** + * Returns the list of installed keyboards with unique packageID/keyboardID + */ + public List getInstalledPackagesList() { + if (!isInitialized) { + KMLog.LogError(TAG, "getInstalledPackagesList while KeyboardController() not initialized"); + return null; + } + synchronized (list) { + List packagesList = new ArrayList(); + // Iterate through the installed keyboards list to find unique packageID/keyboardID + for (int i=0; i + */ + private List getKeyboards(JSONObject keyboardJSON, Keyboard baseKeyboard, + boolean excludeInstalledLanguages ) { + List list = new ArrayList(); + String packageID = baseKeyboard.getPackageID(); + String keyboardID = baseKeyboard.getKeyboardID(); + try { + JSONArray languages = keyboardJSON.getJSONArray("languages"); + for (int j = 0; j < languages.length(); j++) { + JSONObject language = languages.getJSONObject(j); + String languageID = language.getString("id"); + String languageName = language.getString("name"); + if (!excludeInstalledLanguages || + !(KeyboardController.getInstance().keyboardExists(packageID, keyboardID, languageID))) { + // Copy keyboard info and update language + Keyboard newKeyboard = new Keyboard(baseKeyboard); + newKeyboard.setLanguage(languageID, languageName); + list.add(newKeyboard); + } + } + } catch (Exception e) { + KMLog.LogException(TAG, "getKeyboards() ", e); + } + return list; + } + + /** + * Get a list of available keyboard and language pairings that are available to add + * (parses the kmp.json for the language list) + * @param packageID - String of the package ID + * @param keyboardID - String of the keyboard ID + * @param excludeInstalledLanguages - Boolean whether to exclude + * installed languages from the returned list. + * @return List of based on kmp.json. If excludeInstalledLanguages is true, this list + * excludes languages already installed + */ + public List getKeyboardList(String packageID, String keyboardID, boolean excludeInstalledLanguages) { + File packagePath = new File(resourceRoot, KMManager.KMDefault_AssetPackages + File.separator + packageID); + List list = new ArrayList(); + JSONObject infoJSON = loadPackageInfo(packagePath); + try { + JSONArray keyboards = infoJSON.getJSONArray("keyboards"); + + for (int i = 0; i < keyboards.length(); i++) { + JSONObject keyboard = keyboards.getJSONObject(i); + if (keyboardID.equals(keyboard.getString("id"))) { + // Find the keyboard already installed. We'll use it as the base + // for creating new keyboards + int baseKeyboardIndex = KeyboardController.getInstance().getKeyboardIndex(packageID, keyboardID, ""); + if (baseKeyboardIndex == KeyboardController.INDEX_NOT_FOUND) { + continue; + } + Keyboard baseKeyboard = KeyboardController.getInstance().getKeyboardInfo(baseKeyboardIndex); + return getKeyboards(keyboard, baseKeyboard, excludeInstalledLanguages); + } + } + } catch (Exception e) { + KMLog.LogException(TAG, "getKeyboardList() ", e); + } + return list; + } + /** * The master KMP processing method; use after a .kmp download to fully install within the filesystem. * This will overwrite an existing package.