Add Dictionary back to keyboard.

This commit is contained in:
J-D-K 2025-11-29 10:54:51 -05:00
parent 3f55bf8ef9
commit 3b9072ea83
13 changed files with 171 additions and 46 deletions

View File

@ -33,7 +33,8 @@ include $(DEVKITPRO)/libnx/switch_rules
TARGET := JKSV
BUILD := build
SOURCES := source source/appstates source/config source/curl source/data source/fs \
source/logging source/remote source/strings source/sys source/tasks source/ui
source/keyboard source/logging source/remote source/strings source/sys \
source/tasks source/ui
DATA := data
INCLUDES := include ./Libraries/FsLib/Switch/FsLib/include ./Libraries/SDLLib/SDL/include
EXEFS_SRC := exefs_src

View File

@ -0,0 +1,45 @@
#pragma once
#include <initializer_list>
#include <string>
#include <switch.h>
#include <vector>
namespace keyboard
{
class Dictionary final
{
public:
/// @brief Length of the words.
static constexpr size_t WORD_LENGTH = 0x19;
// clang-format off
struct Word
{
/// @brief Need to confirm, but I'm pretty sure this is what the system uses to predict?
char16_t predict[WORD_LENGTH]{};
/// @brief This is the actual word.
char16_t word[WORD_LENGTH]{};
};
// clang-format on
/// @brief Default constructor.
Dictionary() = default;
/// @brief Constructs a new dictionary using the list passed.
Dictionary(std::initializer_list<std::string_view> wordList);
/// @brief Adds the list to the internal list.
void add_list(std::initializer_list<std::string_view> wordList);
/// @brief Returns the number of words in the internal list.
size_t get_count() const noexcept;
/// @brief Returns the pointer to the internal word vector data.
const Dictionary::Word *get_words() const noexcept;
private:
/// @brief Vector of words.
std::vector<Dictionary::Word> m_words{};
};
}

View File

@ -1,4 +1,7 @@
#pragma once
#include "keyboard/Dictionary.hpp"
#include <optional>
#include <string_view>
#include <switch.h>
@ -10,10 +13,12 @@ namespace keyboard
/// @param header The header of the keyboard.
/// @param stringOut Pointer to buffer to write to.
/// @param stringLength Size of the buffer to write too.
/// @param dictionary Optional. Dictionary/words.
/// @return True if input was successful and valid. False if it wasn't.
bool get_input(SwkbdType keyboardType,
std::string_view defaultText,
std::string_view header,
char *stringOut,
size_t stringLength);
size_t stringLength,
std::optional<std::reference_wrapper<keyboard::Dictionary>> dictionary = std::nullopt);
} // namespace keyboard

View File

@ -10,7 +10,7 @@
#include "fslib.hpp"
#include "graphics/colors.hpp"
#include "input.hpp"
#include "keyboard.hpp"
#include "keyboard/keyboard.hpp"
#include "sdl.hpp"
#include "strings/strings.hpp"
#include "stringutil.hpp"
@ -274,8 +274,19 @@ void BackupMenuState::name_and_create_backup()
std::snprintf(name, SIZE_NAME_LENGTH, "%s - %s", nickname, date.c_str());
}
// Doing thing like this so the strings don't linger.
keyboard::Dictionary dictionary{};
{
const std::string dateA = stringutil::get_date_string();
const std::string dateB = stringutil::get_date_string(stringutil::DateFormat::YearDayMonth);
const std::string user = m_user->get_path_safe_nickname();
dictionary.add_list({dateA, dateB, user, ".zip"});
}
const char *keyboardHeader = strings::get_by_name(strings::names::KEYBOARD, 0);
const bool named = autoNamed || keyboard::get_input(SwkbdType_QWERTY, name, keyboardHeader, name, SIZE_NAME_LENGTH);
const bool named =
autoNamed || keyboard::get_input(SwkbdType_QWERTY, name, keyboardHeader, name, SIZE_NAME_LENGTH, dictionary);
if (!named) { return; }
m_dataStruct->killTask = true; // Need to make sure these kill the task.

View File

@ -6,7 +6,7 @@
#include "error.hpp"
#include "graphics/colors.hpp"
#include "input.hpp"
#include "keyboard.hpp"
#include "keyboard/keyboard.hpp"
#include "strings/strings.hpp"
#include "ui/PopMessageManager.hpp"

View File

@ -9,7 +9,7 @@
#include "fs/fs.hpp"
#include "fslib.hpp"
#include "input.hpp"
#include "keyboard.hpp"
#include "keyboard/keyboard.hpp"
#include "logging/logger.hpp"
#include "mathutil.hpp"
#include "strings/strings.hpp"

View File

@ -6,7 +6,7 @@
#include "error.hpp"
#include "fs/fs.hpp"
#include "input.hpp"
#include "keyboard.hpp"
#include "keyboard/keyboard.hpp"
#include "logging/logger.hpp"
#include "strings/strings.hpp"
#include "stringutil.hpp"

View File

@ -10,7 +10,7 @@
#include "fslib.hpp"
#include "graphics/colors.hpp"
#include "input.hpp"
#include "keyboard.hpp"
#include "keyboard/keyboard.hpp"
#include "logging/logger.hpp"
#include "strings/strings.hpp"
#include "stringutil.hpp"

View File

@ -11,7 +11,7 @@
#include "fslib.hpp"
#include "graphics/colors.hpp"
#include "input.hpp"
#include "keyboard.hpp"
#include "keyboard/keyboard.hpp"
#include "logging/logger.hpp"
#include "remote/remote.hpp"
#include "strings/strings.hpp"

View File

@ -1,36 +0,0 @@
#include "keyboard.hpp"
#include "error.hpp"
#include <string>
bool keyboard::get_input(SwkbdType keyboardType,
std::string_view defaultText,
std::string_view header,
char *stringOut,
size_t stringLength)
{
SwkbdConfig keyboard{};
const bool createError = error::libnx(swkbdCreate(&keyboard, 0));
if (createError) { return false; }
swkbdConfigSetBlurBackground(&keyboard, true);
swkbdConfigSetInitialText(&keyboard, defaultText.data());
swkbdConfigSetHeaderText(&keyboard, header.data());
swkbdConfigSetGuideText(&keyboard, header.data());
swkbdConfigSetType(&keyboard, keyboardType);
swkbdConfigSetStringLenMax(&keyboard, stringLength);
swkbdConfigSetKeySetDisableBitmask(&keyboard, SwkbdKeyDisableBitmask_Backslash);
const bool swkbdError = error::libnx(swkbdShow(&keyboard, stringOut, stringLength));
const bool empty = std::char_traits<char>::length(stringOut) == 0;
if (swkbdError || empty)
{
swkbdClose(&keyboard);
return false;
}
swkbdClose(&keyboard);
return true;
}

View File

@ -0,0 +1,37 @@
#include "keyboard/Dictionary.hpp"
#include "logging/logger.hpp"
// ---- Construction ----
keyboard::Dictionary::Dictionary(std::initializer_list<std::string_view> wordList) { Dictionary::add_list(wordList); }
// ---- Public functions ----
void keyboard::Dictionary::add_list(std::initializer_list<std::string_view> wordList)
{
// Loop through the list.
for (const std::string_view word : wordList)
{
// New word
Dictionary::Word newWord{};
// This is cleaner and easier to read. libnx expects uint16 instead of char16
uint16_t *predict = reinterpret_cast<uint16_t *>(newWord.predict);
uint16_t *dictWord = reinterpret_cast<uint16_t *>(newWord.word);
// Same here.
const uint8_t *inData = reinterpret_cast<const uint8_t *>(word.data());
// The words are UTF-16. We need to convert them.
utf8_to_utf16(predict, inData, Dictionary::WORD_LENGTH);
utf8_to_utf16(dictWord, inData, Dictionary::WORD_LENGTH);
// Push the word to the vector.
m_words.push_back(newWord);
}
}
size_t keyboard::Dictionary::get_count() const noexcept { return m_words.size(); }
const keyboard::Dictionary::Word *keyboard::Dictionary::get_words() const noexcept { return m_words.data(); }

View File

@ -0,0 +1,62 @@
#include "keyboard/keyboard.hpp"
#include "error.hpp"
#include <string>
bool keyboard::get_input(SwkbdType keyboardType,
std::string_view defaultText,
std::string_view header,
char *stringOut,
size_t stringLength,
std::optional<std::reference_wrapper<keyboard::Dictionary>> dictionary)
{
// Swkbd config.
SwkbdConfig keyboard{};
// Cache instead of repeated calls.
const bool hasDictionary = dictionary.has_value();
// This changes whether or not we're passed a dictionary here.
bool createError{};
if (hasDictionary)
{
// Getting this out of the optional looks confusing...
const size_t wordCount = dictionary->get().get_count();
createError = error::libnx(swkbdCreate(&keyboard, wordCount));
}
else { createError = error::libnx(swkbdCreate(&keyboard, 0)); }
// Just return false if we can't init the keyboard.
if (createError) { return false; }
// Standard swkbd init.
swkbdConfigSetBlurBackground(&keyboard, true);
swkbdConfigSetInitialText(&keyboard, defaultText.data());
swkbdConfigSetHeaderText(&keyboard, header.data());
swkbdConfigSetGuideText(&keyboard, header.data());
swkbdConfigSetType(&keyboard, keyboardType);
swkbdConfigSetStringLenMax(&keyboard, stringLength);
swkbdConfigSetKeySetDisableBitmask(&keyboard, SwkbdKeyDisableBitmask_Backslash);
// Add the dictionary if one was passed.
if (hasDictionary)
{
// These are easier to read and work with.
const SwkbdDictWord *words = reinterpret_cast<const SwkbdDictWord *>(dictionary->get().get_words());
const size_t wordCount = dictionary->get().get_count();
swkbdConfigSetDictionary(&keyboard, words, wordCount);
}
const bool swkbdError = error::libnx(swkbdShow(&keyboard, stringOut, stringLength));
const bool empty = std::char_traits<char>::length(stringOut) == 0;
if (swkbdError || empty)
{
swkbdClose(&keyboard);
return false;
}
swkbdClose(&keyboard);
return true;
}

View File

@ -4,7 +4,7 @@
#include "data/data.hpp"
#include "error.hpp"
#include "fs/fs.hpp"
#include "keyboard.hpp"
#include "keyboard/keyboard.hpp"
#include "logging/logger.hpp"
#include "remote/remote.hpp"
#include "strings/strings.hpp"