179 lines
6.8 KiB
C#
179 lines
6.8 KiB
C#
/*
|
|
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
|
|
|
|
Keepass2Android 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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Keepass2Android 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 Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
using System;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using Android.App;
|
|
using Android.Content;
|
|
using Android.Content.PM;
|
|
using Android.OS;
|
|
using Android.Widget;
|
|
using Android.Provider;
|
|
using Android.Views.Autofill;
|
|
using Java.IO;
|
|
using KeePass.DataExchange;
|
|
using KeePassLib.Cryptography.Cipher;
|
|
using KeePassLib.Keys;
|
|
using KeePassLib.Serialization;
|
|
using KeePassLib.Utility;
|
|
using keepass2android.Io;
|
|
using keepass2android.Utils;
|
|
using KeePassLib;
|
|
using KeePassLib.Cryptography.KeyDerivation;
|
|
using KeePassLib.Interfaces;
|
|
using System.Collections.Generic;
|
|
using AndroidX.Preference;
|
|
using keepass2android;
|
|
|
|
|
|
namespace keepass2android
|
|
{
|
|
|
|
/// <summary>
|
|
/// <para>
|
|
/// A helper class that manages language preference display and selection.
|
|
/// </para>
|
|
/// <para>
|
|
/// The idea is to provide a ListPreference with a "System language" item at the top, followed by
|
|
/// the localized list of supported language names. The items are backed by their corresponding "code".
|
|
/// For a langauge that's the 2-char lowercase language code, which is exactly the same code that
|
|
/// LocaleManager.Language expects.
|
|
/// </para>
|
|
/// <para>
|
|
/// "System language" is a special case. LocaleManager.Language expects null, but ListPreference
|
|
/// does not support null as a valid code. To work around this, LanguageEntry.SYS_LANG_CODE
|
|
/// is used as the preference code. LanguageEntry.PrefCodeToLanguage(string) is used to convert the
|
|
/// preference codes to language codes as needed.
|
|
/// </para>
|
|
/// </summary>
|
|
internal class AppLanguageManager
|
|
{
|
|
private readonly PreferenceFragmentCompat _fragment;
|
|
private readonly AndroidX.Preference.ListPreference _langPref;
|
|
private readonly Dictionary<string, LanguageEntry> _langEntriesByCodeUnique;
|
|
|
|
public AppLanguageManager(PreferenceFragmentCompat fragment, AndroidX.Preference.ListPreference langPref, HashSet<string> supportedLocales)
|
|
{
|
|
this._fragment = fragment;
|
|
this._langPref = langPref;
|
|
this._langEntriesByCodeUnique = CreateCodeToEntryMapping(fragment, supportedLocales);
|
|
|
|
ConfigureLanguageList();
|
|
}
|
|
|
|
private static Dictionary<string, LanguageEntry> CreateCodeToEntryMapping(PreferenceFragmentCompat fragment, HashSet<string> supportedLocales)
|
|
{
|
|
var localesByCode = new Dictionary<string, List<Java.Util.Locale>>();
|
|
foreach (var loc in Java.Util.Locale.GetAvailableLocales())
|
|
{
|
|
if (!supportedLocales.Contains(loc.Language))
|
|
continue;
|
|
if (!localesByCode.ContainsKey(loc.Language))
|
|
{
|
|
localesByCode[loc.Language] = new List<Java.Util.Locale>();
|
|
}
|
|
localesByCode[loc.Language].Add(loc);
|
|
}
|
|
|
|
var langEntriesByCodeUnique = localesByCode
|
|
.Select(l => new KeyValuePair<string, LanguageEntry>(l.Key, LanguageEntry.OfLocale(l.Value.First())))
|
|
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
|
|
|
var sysLangEntry = LanguageEntry.SystemDefault(fragment.GetString(Resource.String.SystemLanguage));
|
|
langEntriesByCodeUnique.Add(sysLangEntry.Code, sysLangEntry);
|
|
|
|
return langEntriesByCodeUnique;
|
|
}
|
|
|
|
private void ConfigureLanguageList()
|
|
{
|
|
List<KeyValuePair<string, LanguageEntry>> langEntriesList = _langEntriesByCodeUnique
|
|
.OrderByDescending(kvp => kvp.Value.IsSystem)
|
|
.ThenBy(kvp => kvp.Value.Name)
|
|
.ToList();
|
|
|
|
_langPref.SetEntries(langEntriesList
|
|
.Select(kvp => kvp.Value.Name)
|
|
.ToArray());
|
|
_langPref.SetEntryValues(langEntriesList
|
|
.Select(kvp => kvp.Value.Code)
|
|
.ToArray());
|
|
|
|
_langPref.Summary = GetDisplayLanguage(LanguageEntry.PrefCodeToLanguage(_langPref.Value));
|
|
_langPref.PreferenceChange += AppLanguagePrefChange;
|
|
}
|
|
|
|
private string GetDisplayLanguage(string languageCode)
|
|
{
|
|
if (languageCode != null && this._langEntriesByCodeUnique.ContainsKey(languageCode))
|
|
return this._langEntriesByCodeUnique[languageCode]?.Name;
|
|
else
|
|
return _fragment.GetString(Resource.String.SystemLanguage);
|
|
}
|
|
|
|
private void AppLanguagePrefChange(object sender, AndroidX.Preference.Preference.PreferenceChangeEventArgs args)
|
|
{
|
|
string langCode = LanguageEntry.PrefCodeToLanguage((string)args.NewValue);
|
|
LocaleManager.Language = langCode;
|
|
_langPref.Summary = GetDisplayLanguage(langCode);
|
|
}
|
|
}
|
|
|
|
#pragma warning restore CS0618 // Type or member is obsolete
|
|
|
|
|
|
/// <summary>
|
|
/// Activity to configure the application and database settings. The database must be unlocked, and this activity will close if it becomes locked.
|
|
/// </summary>
|
|
[Activity(Label = "@string/app_name", Theme = "@style/Kp2aTheme_ActionBar", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden)]
|
|
public class DatabaseSettingsActivity : LockCloseActivity, PreferenceFragmentCompat.IOnPreferenceStartFragmentCallback
|
|
{
|
|
|
|
public static void Launch(Activity ctx)
|
|
{
|
|
ctx.StartActivity(new Intent(ctx, typeof(DatabaseSettingsActivity)));
|
|
}
|
|
|
|
private ActivityDesign _design;
|
|
|
|
public DatabaseSettingsActivity()
|
|
{
|
|
_design = new ActivityDesign(this);
|
|
settingsFragmentManager = new SettingsFragmentManager(this);
|
|
}
|
|
|
|
protected override void OnCreate(Bundle savedInstanceState)
|
|
{
|
|
_design.ApplyTheme();
|
|
base.OnCreate(savedInstanceState);
|
|
|
|
|
|
}
|
|
|
|
public SettingsFragmentManager settingsFragmentManager;
|
|
public bool OnPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref)
|
|
{
|
|
return settingsFragmentManager.OnPreferenceStartFragment(caller, pref);
|
|
}
|
|
|
|
}
|
|
}
|
|
|