Merge pull request #220 from jpirnay/feat-txt-font
feat: Add a default font for .txt / .md files
This commit is contained in:
@@ -286,7 +286,7 @@ void ActivityManager::goToBrowser() {
|
||||
|
||||
void ActivityManager::goToReader(std::string path) {
|
||||
RenderLock lock;
|
||||
ensureSdFontLoaded();
|
||||
ensureSdFontLoadedForPath(path.c_str());
|
||||
replaceActivity(std::make_unique<ReaderActivity>(renderer, mappedInput, std::move(path)));
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ void ActivityManager::replaceWithReader(std::string path, ReturnHint hint) {
|
||||
returnHint = std::move(hint);
|
||||
hasReturnHint = true;
|
||||
RenderLock lock;
|
||||
ensureSdFontLoaded();
|
||||
ensureSdFontLoadedForPath(path.c_str());
|
||||
replaceActivity(std::make_unique<ReaderActivity>(renderer, mappedInput, std::move(path)));
|
||||
}
|
||||
|
||||
|
||||
@@ -494,7 +494,7 @@ BookOverlayInfo SleepActivity::getBookOverlayInfo(const std::string& bookPath) c
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
} else if (FsHelpers::checkFileExtension(bookPath, ".txt")) {
|
||||
} else if (FsHelpers::hasTxtExtension(bookPath) || FsHelpers::hasMarkdownExtension(bookPath)) {
|
||||
Txt txt(bookPath, "/.crosspoint");
|
||||
if (txt.load()) {
|
||||
info.title = txt.getTitle();
|
||||
@@ -834,7 +834,7 @@ void SleepActivity::renderOverlaySleepScreen() const {
|
||||
|
||||
if (FsHelpers::checkFileExtension(path, ".xtc") || FsHelpers::checkFileExtension(path, ".xtch")) {
|
||||
rendered = XtcReaderActivity::drawCurrentPageToBuffer(path, renderer);
|
||||
} else if (FsHelpers::checkFileExtension(path, ".txt")) {
|
||||
} else if (FsHelpers::hasTxtExtension(path) || FsHelpers::hasMarkdownExtension(path)) {
|
||||
rendered = TxtReaderActivity::drawCurrentPageToBuffer(path, renderer);
|
||||
} else if (FsHelpers::checkFileExtension(path, ".epub")) {
|
||||
rendered = EpubReaderActivity::drawCurrentPageToBuffer(path, renderer);
|
||||
|
||||
@@ -325,7 +325,7 @@ void MdReaderActivity::initializeReader() {
|
||||
return;
|
||||
}
|
||||
|
||||
cachedFontId = SETTINGS.getReaderFontId();
|
||||
cachedFontId = SETTINGS.getTxtReaderFontId();
|
||||
cachedScreenMargin = SETTINGS.screenMargin;
|
||||
cachedParagraphAlignment = SETTINGS.paragraphAlignment;
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ void TxtReaderActivity::initializeReader() {
|
||||
}
|
||||
|
||||
// Store current settings for cache validation
|
||||
cachedFontId = SETTINGS.getReaderFontId();
|
||||
cachedFontId = SETTINGS.getTxtReaderFontId();
|
||||
cachedScreenMargin = SETTINGS.screenMargin;
|
||||
cachedParagraphAlignment = SETTINGS.paragraphAlignment;
|
||||
|
||||
@@ -710,7 +710,7 @@ bool TxtReaderActivity::drawCurrentPageToBuffer(const std::string& filePath, Gfx
|
||||
}
|
||||
|
||||
// Compute layout values that match what initializeReader() produces
|
||||
const int fontId = SETTINGS.getReaderFontId();
|
||||
const int fontId = SETTINGS.getTxtReaderFontId();
|
||||
const uint8_t screenMargin = SETTINGS.screenMargin;
|
||||
const uint8_t paragraphAlignment = SETTINGS.paragraphAlignment;
|
||||
|
||||
|
||||
@@ -6,28 +6,12 @@
|
||||
#include "MappedInputManager.h"
|
||||
#include "SdCardFontGlobals.h"
|
||||
#include "components/UITheme.h"
|
||||
#include "fontIds.h"
|
||||
|
||||
namespace {
|
||||
|
||||
uint8_t currentFontIndex() {
|
||||
if (SETTINGS.sdFontFamilyName[0] != '\0') {
|
||||
const auto& families = sdFontSystem.registry().getFamilies();
|
||||
for (int i = 0; i < static_cast<int>(families.size()); i++) {
|
||||
if (families[i].name == SETTINGS.sdFontFamilyName) {
|
||||
return static_cast<uint8_t>(CrossPointSettings::BUILTIN_FONT_COUNT + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return SETTINGS.fontFamily < CrossPointSettings::BUILTIN_FONT_COUNT ? SETTINGS.fontFamily : 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void FontSelectionActivity::onEnter() {
|
||||
Activity::onEnter();
|
||||
fontCount = fontFamilyOptionCount();
|
||||
selectedIndex = currentFontIndex();
|
||||
selectedIndex =
|
||||
static_cast<int>(target == Target::TXT ? txtFontFamilyDynamicGetter(nullptr) : fontFamilyDynamicGetter(nullptr));
|
||||
if (selectedIndex >= fontCount) selectedIndex = 0;
|
||||
requestUpdate();
|
||||
}
|
||||
@@ -50,7 +34,11 @@ void FontSelectionActivity::loop() {
|
||||
}
|
||||
|
||||
void FontSelectionActivity::handleSelection() {
|
||||
fontFamilyDynamicSetter(nullptr, static_cast<uint8_t>(selectedIndex));
|
||||
if (target == Target::TXT) {
|
||||
txtFontFamilyDynamicSetter(nullptr, static_cast<uint8_t>(selectedIndex));
|
||||
} else {
|
||||
fontFamilyDynamicSetter(nullptr, static_cast<uint8_t>(selectedIndex));
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -60,13 +48,15 @@ void FontSelectionActivity::render(RenderLock&&) {
|
||||
const auto& metrics = UITheme::getInstance().getMetrics();
|
||||
const Rect contentRect = UITheme::getContentRect(renderer, true, false);
|
||||
|
||||
const StrId headerStr = target == Target::TXT ? StrId::STR_TXT_FONT_FAMILY : StrId::STR_FONT_FAMILY;
|
||||
GUI.drawHeader(renderer, Rect{contentRect.x, metrics.topPadding, contentRect.width, metrics.headerHeight},
|
||||
tr(STR_FONT_FAMILY));
|
||||
I18N.get(headerStr));
|
||||
|
||||
const int contentTop = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing;
|
||||
const int contentHeight = contentRect.height - contentTop - metrics.verticalSpacing;
|
||||
|
||||
const uint8_t activeIndex = currentFontIndex();
|
||||
const uint8_t activeIndex = static_cast<uint8_t>(target == Target::TXT ? txtFontFamilyDynamicGetter(nullptr)
|
||||
: fontFamilyDynamicGetter(nullptr));
|
||||
GUI.drawList(
|
||||
renderer, Rect{contentRect.x, contentTop, contentRect.width, contentHeight}, fontCount, selectedIndex,
|
||||
[](int index) { return fontFamilyOptionLabel(static_cast<uint8_t>(index)); }, nullptr, nullptr,
|
||||
|
||||
@@ -11,8 +11,10 @@ class MappedInputManager;
|
||||
/// Replaces in-place enum cycling for the Reader Font Family setting.
|
||||
class FontSelectionActivity final : public Activity {
|
||||
public:
|
||||
explicit FontSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput)
|
||||
: Activity("FontSelect", renderer, mappedInput) {}
|
||||
enum class Target { EPUB, TXT };
|
||||
|
||||
explicit FontSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, Target target = Target::EPUB)
|
||||
: Activity("FontSelect", renderer, mappedInput), target(target) {}
|
||||
|
||||
void onEnter() override;
|
||||
void onExit() override;
|
||||
@@ -25,4 +27,5 @@ class FontSelectionActivity final : public Activity {
|
||||
ButtonNavigator buttonNavigator;
|
||||
int selectedIndex = 0;
|
||||
uint8_t fontCount = 0;
|
||||
Target target;
|
||||
};
|
||||
|
||||
@@ -221,9 +221,18 @@ struct SettingInfo {
|
||||
}
|
||||
|
||||
bool isSeparator = false;
|
||||
bool usesSelectorActivity = false; // Confirm opens a full-screen selector instead of inline cycling
|
||||
StrId subcategory = StrId::STR_NONE_OPT; // Triggers a separator row on first use and on change
|
||||
StrId submenu = StrId::STR_NONE_OPT; // Routes item into a submenu; hidden from main list
|
||||
|
||||
// Marks this entry as requiring a full-screen selector activity on Confirm
|
||||
// (instead of inline value cycling). The SettingsActivity / SettingsSubmenuActivity
|
||||
// intercept entries with this flag before toggleValue() is called.
|
||||
SettingInfo& withSelectorActivity() {
|
||||
usesSelectorActivity = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Inserts a separator row in the parent tab when this item's subcategory first appears or changes.
|
||||
SettingInfo& withSubcategory(StrId sub) {
|
||||
subcategory = sub;
|
||||
|
||||
@@ -81,10 +81,11 @@ void SettingsActivity::onEnter() {
|
||||
setting.nameId == StrId::STR_TIMEZONE)) {
|
||||
continue;
|
||||
}
|
||||
// Enrich the font-family entry with SD card families discovered at boot.
|
||||
// Enrich font-family entries with SD card families discovered at boot.
|
||||
// The list itself is a namespace-static; we only mutate our local copy here.
|
||||
SettingInfo enriched = setting;
|
||||
if (setting.key && std::strcmp(setting.key, "fontFamily") == 0) {
|
||||
if (setting.key &&
|
||||
(std::strcmp(setting.key, "fontFamily") == 0 || std::strcmp(setting.key, "txtFontFamily") == 0)) {
|
||||
const uint8_t n = fontFamilyOptionCount();
|
||||
enriched.enumLabels.clear();
|
||||
enriched.enumLabels.reserve(n);
|
||||
@@ -96,8 +97,8 @@ void SettingsActivity::onEnter() {
|
||||
continue;
|
||||
}
|
||||
const bool isReaderFontEntry =
|
||||
enriched.category == StrId::STR_CAT_READER && (enriched.subcategory == StrId::STR_MENU_READER_FONT ||
|
||||
enriched.submenu == StrId::STR_MENU_READER_FONT_SETTINGS);
|
||||
enriched.category == StrId::STR_CAT_READER &&
|
||||
(enriched.submenu == StrId::STR_MENU_READER_FONT || enriched.submenu == StrId::STR_MENU_TXT_FONT);
|
||||
|
||||
if (!insertedFontDownload && sawReaderFontSection && !isReaderFontEntry) {
|
||||
insertFontDownloadBelowFontSection();
|
||||
@@ -277,8 +278,10 @@ void SettingsActivity::toggleCurrentSetting() {
|
||||
const auto& setting = (*currentSettings)[selectedSetting];
|
||||
if (setting.isSeparator) return;
|
||||
|
||||
if (setting.type == SettingType::ENUM && setting.nameId == StrId::STR_FONT_FAMILY) {
|
||||
startActivityForResult(std::make_unique<FontSelectionActivity>(renderer, mappedInput),
|
||||
if (setting.usesSelectorActivity) {
|
||||
const auto target = (setting.valueGetter == txtFontFamilyDynamicGetter) ? FontSelectionActivity::Target::TXT
|
||||
: FontSelectionActivity::Target::EPUB;
|
||||
startActivityForResult(std::make_unique<FontSelectionActivity>(renderer, mappedInput, target),
|
||||
[this](const ActivityResult&) {
|
||||
SETTINGS.saveToFile();
|
||||
needsHalfRefresh = true;
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
#include <I18n.h>
|
||||
|
||||
#include "CrossPointSettings.h"
|
||||
#include "FontSelectionActivity.h"
|
||||
#include "MappedInputManager.h"
|
||||
#include "SdCardFontGlobals.h"
|
||||
#include "SettingActionDispatch.h"
|
||||
#include "components/UITheme.h"
|
||||
#include "fontIds.h"
|
||||
@@ -48,6 +50,26 @@ std::string SettingsSubmenuActivity::getItemValueString(int index) const {
|
||||
return MenuListActivity::getItemValueString(index);
|
||||
}
|
||||
|
||||
void SettingsSubmenuActivity::toggleCurrentItem() {
|
||||
if (selectedIndex < 0 || selectedIndex >= static_cast<int>(menuItems.size())) return;
|
||||
const auto& setting = menuItems[selectedIndex];
|
||||
if (setting.isSeparator) return;
|
||||
|
||||
if (setting.usesSelectorActivity) {
|
||||
const auto target = (setting.valueGetter == txtFontFamilyDynamicGetter) ? FontSelectionActivity::Target::TXT
|
||||
: FontSelectionActivity::Target::EPUB;
|
||||
startActivityForResult(std::make_unique<FontSelectionActivity>(renderer, mappedInput, target),
|
||||
[this](const ActivityResult&) {
|
||||
SETTINGS.saveToFile();
|
||||
needsHalfRefresh = true;
|
||||
requestUpdate();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
MenuListActivity::toggleCurrentItem();
|
||||
}
|
||||
|
||||
void SettingsSubmenuActivity::onSettingToggled(int /*index*/) { SETTINGS.saveToFile(); }
|
||||
|
||||
void SettingsSubmenuActivity::render(RenderLock&&) {
|
||||
|
||||
@@ -16,6 +16,7 @@ class SettingsSubmenuActivity final : public MenuListActivity {
|
||||
|
||||
// MenuListActivity overrides
|
||||
void onEnter() override;
|
||||
void toggleCurrentItem() override;
|
||||
void onActionSelected(int index) override;
|
||||
void onSettingToggled(int index) override;
|
||||
std::string getItemValueString(int index) const override;
|
||||
|
||||
Reference in New Issue
Block a user