improve UI for user-added dictionaries

This commit is contained in:
Helium314 2023-07-07 06:32:48 +02:00
parent 4a5d3155b4
commit c53224dd2b
2 changed files with 88 additions and 58 deletions

View file

@ -13,6 +13,8 @@ import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants
@ -20,6 +22,7 @@ import org.dslul.openboard.inputmethod.latin.BinaryDictionaryGetter
import org.dslul.openboard.inputmethod.latin.R
import org.dslul.openboard.inputmethod.latin.common.FileUtils
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils
import org.dslul.openboard.inputmethod.latin.makedict.DictionaryHeader
import org.dslul.openboard.inputmethod.latin.utils.DialogUtils
import org.dslul.openboard.inputmethod.latin.utils.DictionaryInfoUtils
import java.io.File
@ -114,57 +117,73 @@ class DictionarySettingsFragment : SubScreenFragment() {
if (currentDictLocale == null && currentDictState != DICT_NEW)
return
var dialog: AlertDialog? = null
val link = "<a href='$DICTIONARY_URL'>" +
resources.getString(R.string.dictionary_link_text) + "</a>"
val message = if (currentDictState == DICT_NEW)
Html.fromHtml(resources.getString(R.string.add_new_dictionary, link))
else
Html.fromHtml(resources.getString(R.string.update_dictionary, link))
val message = Html.fromHtml(resources.getString(R.string.add_dictionary, link))
val title = if (currentDictState == DICT_NEW) R.string.add_new_dictionary_title
else R.string.dictionary_settings_category
val updateButtonTitle = if (currentDictExistsForUser) R.string.update_dictionary_button
else R.string.user_dict_settings_add_menu_title
val builder = AlertDialog.Builder(DialogUtils.getPlatformDialogThemeContext(activity))
.setNegativeButton(R.string.cancel, null)
.setMessage(message)
.setTitle(title)
.setPositiveButton(updateButtonTitle) { _, _ ->
.setPositiveButton(R.string.user_dict_settings_add_menu_title) { _, _ ->
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType("application/octet-stream")
startActivityForResult(intent, DICTIONARY_REQUEST_CODE)
}
// allow removing dictionaries
if (currentDictExistsForUser) {
builder.setNeutralButton(if (currentDictExistsInternal) R.string.reset_dictionary else R.string.delete_dict) { _, _ ->
AlertDialog.Builder(DialogUtils.getPlatformDialogThemeContext(activity))
.setTitle(R.string.remove_dictionary_title)
.setMessage(resources.getString(R.string.remove_dictionary_message, currentDictLocale?.displayName()))
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.delete_dict) { _,_ ->
currentDictLocale?.getUserDictFilenames()?.let { files ->
var parent: File? = null
files.forEach {
val f = File(it)
parent = f.parentFile
f.delete()
}
if (parent?.list()?.isEmpty() == true)
parent?.delete()
}
reloadDictionaries()
}
.show()
if (!currentDictExistsForUser) {
builder.setMessage(message)
} else {
val l = LinearLayout(activity).apply {
orientation = LinearLayout.VERTICAL
setPadding(30, 30, 30, 10)
}
val filenames = currentDictLocale?.getUserDictFilenames().orEmpty()
if (filenames.isNotEmpty())
l.addView(TextView(activity).apply {
setText(R.string.existing_dictionaries)
textSize = 16f
})
for (fn in filenames) {
val b = Button(activity).apply {
text = getUserDictType(fn)
setOnClickListener {
AlertDialog.Builder(DialogUtils.getPlatformDialogThemeContext(activity))
.setTitle(R.string.remove_dictionary_title)
.setMessage(resources.getString(R.string.remove_dictionary_message, text, currentDictLocale?.displayName()))
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.delete_dict) { _,_ ->
val f = File(fn)
val parent = f.parentFile
f.delete()
if (parent?.list()?.isEmpty() == true)
parent.delete()
val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION)
activity.sendBroadcast(newDictBroadcast)
reloadDictionaries()
dialog?.dismiss()
}
.show()
}
}
l.addView(b)
}
val t = TextView(activity).apply {
text = message
textSize = 16f
}
l.addView(t)
builder.setView(l)
t.movementMethod = LinkMovementMethod.getInstance()
}
val dialog = builder.create()
dialog = builder.create()
dialog.show()
// make links in the HTML text work
(dialog.findViewById<View>(android.R.id.message) as TextView).movementMethod =
LinkMovementMethod.getInstance()
(dialog.findViewById<View>(android.R.id.message) as? TextView)?.movementMethod = LinkMovementMethod.getInstance()
}
// copied from CustomInputStyleSettingsFragment
@ -216,19 +235,35 @@ class DictionarySettingsFragment : SubScreenFragment() {
return
}
val locale = newHeader.mLocaleString.toLocale()
val currentDictLocale = currentDictLocale
if (currentDictLocale != null && locale != currentDictLocale) {
cachedDictionaryFile.delete()
onDictionaryLoadingError(resources.getString(R.string.dictionary_file_wrong_locale, locale.displayName(), currentDictLocale?.displayName()))
val message = resources.getString(
R.string.dictionary_file_wrong_locale,
locale.displayName(),
currentDictLocale.displayName()
)
AlertDialog.Builder(DialogUtils.getPlatformDialogThemeContext(activity))
.setMessage(message)
.setNegativeButton(android.R.string.cancel) { _, _ -> cachedDictionaryFile.delete() }
.setPositiveButton(R.string.dictionary_file_wrong_locale_ok) { _, _ ->
checkCachedDictionaryVersion(currentDictLocale, newHeader)
}
.show()
return
}
checkCachedDictionaryVersion(currentDictLocale ?: locale, newHeader)
}
// baseLocale is the locale to which the dict will be added, not necessarily equal to dict locale
private fun checkCachedDictionaryVersion(baseLocale: Locale, newHeader: DictionaryHeader) {
// idString is content of 'dictionary' key, in format <type>:<locale>
val dictionaryType = newHeader.mIdString.substringBefore(":")
val userDictFile = File(locale.getUserDictFilename(dictionaryType))
val oldDictFile = File(baseLocale.getUserDictFilename(dictionaryType))
// ask for user confirmation if it would be a version downgrade or if user pressed add new,
// but we already have a user dictionary for the same locale
val shouldAskMessageId = if (userDictFile.exists()) {
val oldHeader = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(userDictFile, 0, userDictFile.length())
val shouldAskMessageId = if (oldDictFile.exists()) {
val oldHeader = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(oldDictFile, 0, oldDictFile.length())
if (oldHeader != null && oldHeader.mVersionString.toInt() > newHeader.mVersionString.toInt())
R.string.overwrite_old_dicitonary_messsage
else if (currentDictState == DICT_NEW && currentDictLocale == null)
@ -236,9 +271,9 @@ class DictionarySettingsFragment : SubScreenFragment() {
else 0
} else 0
if (shouldAskMessageId != 0)
showConfirmReplaceDialog(locale, dictionaryType, shouldAskMessageId)
showConfirmReplaceDialog(baseLocale, dictionaryType, shouldAskMessageId)
else
moveCachedFileToDictionaries(locale, dictionaryType)
moveCachedFileToDictionaries(baseLocale, dictionaryType)
}
private fun showConfirmReplaceDialog(locale: Locale, dictionaryType: String, messageId: Int) {
@ -282,25 +317,20 @@ class DictionarySettingsFragment : SubScreenFragment() {
AlertDialog.Builder(DialogUtils.getPlatformDialogThemeContext(activity))
.setNegativeButton(android.R.string.ok, null)
.setMessage(message)
.setTitle("loading error")
.show()
}
private fun Locale.getUserDictFilename(dictionaryType: String) =
DictionaryInfoUtils.getCacheDirectoryForLocale(this.toString(), activity) + File.separator + dictionaryType + "_" + USER_DICTIONARY_SUFFIX
private fun getUserDictType(dictionaryFilename: String) = dictionaryFilename.substringAfterLast(File.separator).substringBefore("_$USER_DICTIONARY_SUFFIX")
private fun Locale.getUserDictFilenames(): List<String> {
val dicts = mutableListOf<String>()
val p = DictionaryInfoUtils.getCacheDirectoryForLocale(this.toString(), activity)
DictionaryInfoUtils.getCachedDirectoryList(activity)?.forEach { dir ->
if (!dir.isDirectory)
return@forEach
dir.list()?.forEach {
if (it.endsWith(USER_DICTIONARY_SUFFIX))
dicts.add(p + File.separator + it)
}
val dir = File(DictionaryInfoUtils.getCacheDirectoryForLocale(this.toString(), activity))
if (dir.exists() && dir.isDirectory) {
return dir.listFiles { _, name -> name.endsWith(USER_DICTIONARY_SUFFIX) }?.map { it.absolutePath }.orEmpty()
}
return dicts
return emptyList()
}
private fun Locale.getInternalDictFilename() =

View file

@ -500,8 +500,6 @@ disposition rather than other common dispositions for Latin languages. [CHAR LIM
<string name="internal_dictionary_summary">Built-in dictionary</string>
<!-- Title for the adding new user dictionary dialog -->
<string name="add_new_dictionary_title">"Add dictionary from file"</string>
<!-- Button text for updating a dictionary -->
<string name="update_dictionary_button">"Update"</string>
<!-- Message for user dictionary replacement dialog -->
<string name="replace_dictionary_message">"Really replace existing user-added dictionary for %s?"</string>
<!-- Message when trying to replace user dictionary with older version -->
@ -509,15 +507,15 @@ disposition rather than other common dispositions for Latin languages. [CHAR LIM
<!-- Title and confirm button text for user dictionary replacement dialog -->
<string name="replace_dictionary">"Replace dictionary"</string>
<!-- Message for user dictionary remove dialog -->
<string name="remove_dictionary_message">"Really remove user-added dictionaries for %s?"</string>
<string name="remove_dictionary_message">"Really remove user-added dictionary \"%1$s\" for %2$s?"</string>
<!-- Title for user dictionary remove dialog -->
<string name="remove_dictionary_title">"Remove dictionary"</string>
<!-- Button text in user dictionary remove dialog for resetting to default -->
<string name="reset_dictionary">"Reset to default"</string>
<!-- Message for the user dictionary selection dialog. This string will be interpreted as HTML -->
<string name="update_dictionary">"Select a dictionary to replace the current main dictionary. Dictionaries can be downloaded at %s."</string>
<!-- Message for the user dictionary selection dialog. This string will be interpreted as HTML -->
<string name="add_new_dictionary">"Select a new dictionary to be added to the list. Dictionaries can be downloaded at the %s."</string>
<string name="add_dictionary">"Select a dictionary to add. Dictionaries can be downloaded at %s."</string>
<!-- Message above list of user-added dictionaries -->
<string name="existing_dictionaries">"User-added dictionaries, click to remove:"</string>
<!-- Title of the link to the download page inserted into selection message (above) -->
<string name="dictionary_link_text">"project repository"</string>
<!-- Button text for dictionary file selection -->
@ -527,7 +525,9 @@ disposition rather than other common dispositions for Latin languages. [CHAR LIM
<!-- Text shown when dictionary file could not be read -->
<string name="dictionary_file_error">"Error: Selected file is not a valid dictionary file"</string>
<!-- Text shown when dictionary file is not for the selected locale -->
<string name="dictionary_file_wrong_locale">"Error: Selected file is for %1$s, but %2$s was expected"</string>
<string name="dictionary_file_wrong_locale">"The selected file is for %1$s, but %2$s was expected. Still use it for %2$s?"</string>
<!-- Button text for confirm / yes to the dictionary_file_wrong_locale message (above) -->
<string name="dictionary_file_wrong_locale_ok">"Still use"</string>
<!-- Text shown on other errors when loading dictionary file -->
<string name="dictionary_load_error">"Error loading dictionary file"</string>
<!-- Name of the user dictionaries settings category -->