mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-07 08:07:40 +03:00
Traduction initiale
This commit is contained in:
parent
d4ae108d9b
commit
624586ec03
@ -14,7 +14,7 @@ void BootActivity::onEnter() {
|
||||
renderer.clearScreen();
|
||||
renderer.drawImage(CrossLarge, (pageWidth + 128) / 2, (pageHeight - 128) / 2, 128, 128);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "BOOTING");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "DÉMARRAGE");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, CROSSPOINT_VERSION);
|
||||
renderer.displayBuffer();
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
void SleepActivity::onEnter() {
|
||||
Activity::onEnter();
|
||||
renderPopup("Entering Sleep...");
|
||||
renderPopup("Mise en veille...");
|
||||
|
||||
if (SETTINGS.sleepScreen == CrossPointSettings::SLEEP_SCREEN_MODE::BLANK) {
|
||||
return renderBlankSleepScreen();
|
||||
@ -64,13 +64,13 @@ void SleepActivity::renderCustomSleepScreen() const {
|
||||
}
|
||||
|
||||
if (filename.substr(filename.length() - 4) != ".bmp") {
|
||||
Serial.printf("[%lu] [SLP] Skipping non-.bmp file name: %s\n", millis(), name);
|
||||
Serial.printf("[%lu] [SLP] Ignorer les noms de fichiers non-.bmp: %s\n", millis(), name);
|
||||
file.close();
|
||||
continue;
|
||||
}
|
||||
Bitmap bitmap(file);
|
||||
if (bitmap.parseHeaders() != BmpReaderError::Ok) {
|
||||
Serial.printf("[%lu] [SLP] Skipping invalid BMP file: %s\n", millis(), name);
|
||||
Serial.printf("[%lu] [SLP] Ignorer le fichier BMP invalide: %s\n", millis(), name);
|
||||
file.close();
|
||||
continue;
|
||||
}
|
||||
@ -84,7 +84,7 @@ void SleepActivity::renderCustomSleepScreen() const {
|
||||
const auto filename = "/sleep/" + files[randomFileIndex];
|
||||
FsFile file;
|
||||
if (SdMan.openFileForRead("SLP", filename, file)) {
|
||||
Serial.printf("[%lu] [SLP] Randomly loading: /sleep/%s\n", millis(), files[randomFileIndex].c_str());
|
||||
Serial.printf("[%lu] [SLP] Chargement aléatoire: /sleep/%s\n", millis(), files[randomFileIndex].c_str());
|
||||
delay(100);
|
||||
Bitmap bitmap(file);
|
||||
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
||||
@ -103,7 +103,7 @@ void SleepActivity::renderCustomSleepScreen() const {
|
||||
if (SdMan.openFileForRead("SLP", "/sleep.bmp", file)) {
|
||||
Bitmap bitmap(file);
|
||||
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
||||
Serial.printf("[%lu] [SLP] Loading: /sleep.bmp\n", millis());
|
||||
Serial.printf("[%lu] [SLP] Chargement: /sleep.bmp\n", millis());
|
||||
renderBitmapSleepScreen(bitmap);
|
||||
return;
|
||||
}
|
||||
@ -119,7 +119,7 @@ void SleepActivity::renderDefaultSleepScreen() const {
|
||||
renderer.clearScreen();
|
||||
renderer.drawImage(CrossLarge, (pageWidth + 128) / 2, (pageHeight - 128) / 2, 128, 128);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 70, "CrossPoint", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "SLEEPING");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight / 2 + 95, "EN VEILLE");
|
||||
|
||||
// Make sleep screen dark unless light is selected in settings
|
||||
if (SETTINGS.sleepScreen != CrossPointSettings::SLEEP_SCREEN_MODE::LIGHT) {
|
||||
@ -135,34 +135,34 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap) const {
|
||||
const auto pageHeight = renderer.getScreenHeight();
|
||||
float cropX = 0, cropY = 0;
|
||||
|
||||
Serial.printf("[%lu] [SLP] bitmap %d x %d, screen %d x %d\n", millis(), bitmap.getWidth(), bitmap.getHeight(),
|
||||
Serial.printf("[%lu] [SLP] bitmap %d x %d, écran %d x %d\n", millis(), bitmap.getWidth(), bitmap.getHeight(),
|
||||
pageWidth, pageHeight);
|
||||
if (bitmap.getWidth() > pageWidth || bitmap.getHeight() > pageHeight) {
|
||||
// image will scale, make sure placement is right
|
||||
float ratio = static_cast<float>(bitmap.getWidth()) / static_cast<float>(bitmap.getHeight());
|
||||
const float screenRatio = static_cast<float>(pageWidth) / static_cast<float>(pageHeight);
|
||||
|
||||
Serial.printf("[%lu] [SLP] bitmap ratio: %f, screen ratio: %f\n", millis(), ratio, screenRatio);
|
||||
Serial.printf("[%lu] [SLP] ratio bitmap: %f, ratio écran: %f\n", millis(), ratio, screenRatio);
|
||||
if (ratio > screenRatio) {
|
||||
// image wider than viewport ratio, scaled down image needs to be centered vertically
|
||||
if (SETTINGS.sleepScreenCoverMode == CrossPointSettings::SLEEP_SCREEN_COVER_MODE::CROP) {
|
||||
cropX = 1.0f - (screenRatio / ratio);
|
||||
Serial.printf("[%lu] [SLP] Cropping bitmap x: %f\n", millis(), cropX);
|
||||
Serial.printf("[%lu] [SLP] Recadrage de bitmap x: %f\n", millis(), cropX);
|
||||
ratio = (1.0f - cropX) * static_cast<float>(bitmap.getWidth()) / static_cast<float>(bitmap.getHeight());
|
||||
}
|
||||
x = 0;
|
||||
y = std::round((static_cast<float>(pageHeight) - static_cast<float>(pageWidth) / ratio) / 2);
|
||||
Serial.printf("[%lu] [SLP] Centering with ratio %f to y=%d\n", millis(), ratio, y);
|
||||
Serial.printf("[%lu] [SLP] Centrage avec ratio de %f à y=%d\n", millis(), ratio, y);
|
||||
} else {
|
||||
// image taller than viewport ratio, scaled down image needs to be centered horizontally
|
||||
if (SETTINGS.sleepScreenCoverMode == CrossPointSettings::SLEEP_SCREEN_COVER_MODE::CROP) {
|
||||
cropY = 1.0f - (ratio / screenRatio);
|
||||
Serial.printf("[%lu] [SLP] Cropping bitmap y: %f\n", millis(), cropY);
|
||||
Serial.printf("[%lu] [SLP] Recadrage bitmap y: %f\n", millis(), cropY);
|
||||
ratio = static_cast<float>(bitmap.getWidth()) / ((1.0f - cropY) * static_cast<float>(bitmap.getHeight()));
|
||||
}
|
||||
x = std::round((pageWidth - pageHeight * ratio) / 2);
|
||||
y = 0;
|
||||
Serial.printf("[%lu] [SLP] Centering with ratio %f to x=%d\n", millis(), ratio, x);
|
||||
Serial.printf("[%lu] [SLP] Centrage avec ratio de %f à x=%d\n", millis(), ratio, x);
|
||||
}
|
||||
} else {
|
||||
// center the image
|
||||
@ -170,7 +170,7 @@ void SleepActivity::renderBitmapSleepScreen(const Bitmap& bitmap) const {
|
||||
y = (pageHeight - bitmap.getHeight()) / 2;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [SLP] drawing to %d x %d\n", millis(), x, y);
|
||||
Serial.printf("[%lu] [SLP] dessinage à %d x %d\n", millis(), x, y);
|
||||
renderer.clearScreen();
|
||||
renderer.drawBitmap(bitmap, x, y, pageWidth, pageHeight, cropX, cropY);
|
||||
renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
|
||||
@ -205,12 +205,12 @@ void SleepActivity::renderCoverSleepScreen() const {
|
||||
// Handle XTC file
|
||||
Xtc lastXtc(APP_STATE.openEpubPath, "/.crosspoint");
|
||||
if (!lastXtc.load()) {
|
||||
Serial.println("[SLP] Failed to load last XTC");
|
||||
Serial.println("[SLP] Chargement échoué du dernier XTC");
|
||||
return renderDefaultSleepScreen();
|
||||
}
|
||||
|
||||
if (!lastXtc.generateCoverBmp()) {
|
||||
Serial.println("[SLP] Failed to generate XTC cover bmp");
|
||||
Serial.println("[SLP] Génération échoué de bmp de couverture XTC");
|
||||
return renderDefaultSleepScreen();
|
||||
}
|
||||
|
||||
@ -219,12 +219,12 @@ void SleepActivity::renderCoverSleepScreen() const {
|
||||
// Handle EPUB file
|
||||
Epub lastEpub(APP_STATE.openEpubPath, "/.crosspoint");
|
||||
if (!lastEpub.load()) {
|
||||
Serial.println("[SLP] Failed to load last epub");
|
||||
Serial.println("[SLP] Chargement échoué du dernier epub");
|
||||
return renderDefaultSleepScreen();
|
||||
}
|
||||
|
||||
if (!lastEpub.generateCoverBmp()) {
|
||||
Serial.println("[SLP] Failed to generate cover bmp");
|
||||
Serial.println("[SLP] Génération échoué de bmp de couverture");
|
||||
return renderDefaultSleepScreen();
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ void OpdsBookBrowserActivity::onEnter() {
|
||||
currentPath = OPDS_ROOT_PATH;
|
||||
selectorIndex = 0;
|
||||
errorMessage.clear();
|
||||
statusMessage = "Checking WiFi...";
|
||||
statusMessage = "Verification du WiFi...";
|
||||
updateRequired = true;
|
||||
|
||||
xTaskCreate(&OpdsBookBrowserActivity::taskTrampoline, "OpdsBookBrowserTask",
|
||||
@ -70,7 +70,7 @@ void OpdsBookBrowserActivity::loop() {
|
||||
if (state == BrowserState::ERROR) {
|
||||
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
|
||||
state = BrowserState::LOADING;
|
||||
statusMessage = "Loading...";
|
||||
statusMessage = "Chargement...";
|
||||
updateRequired = true;
|
||||
fetchFeed(currentPath);
|
||||
} else if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
|
||||
@ -155,11 +155,11 @@ void OpdsBookBrowserActivity::render() const {
|
||||
const auto pageWidth = renderer.getScreenWidth();
|
||||
const auto pageHeight = renderer.getScreenHeight();
|
||||
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Calibre Library", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Bilbiothèque Calibre", true, EpdFontFamily::BOLD);
|
||||
|
||||
if (state == BrowserState::CHECK_WIFI) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, statusMessage.c_str());
|
||||
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
|
||||
const auto labels = mappedInput.mapLabels("« Retour", "", "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
@ -167,23 +167,23 @@ void OpdsBookBrowserActivity::render() const {
|
||||
|
||||
if (state == BrowserState::LOADING) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, statusMessage.c_str());
|
||||
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
|
||||
const auto labels = mappedInput.mapLabels("« Retour", "", "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == BrowserState::ERROR) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 20, "Error:");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 20, "Erreur:");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 + 10, errorMessage.c_str());
|
||||
const auto labels = mappedInput.mapLabels("« Back", "Retry", "", "");
|
||||
const auto labels = mappedInput.mapLabels("« Retour", "Reéssay.", "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == BrowserState::DOWNLOADING) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 40, "Downloading...");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 40, "Téléchargement...");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2 - 10, statusMessage.c_str());
|
||||
if (downloadTotal > 0) {
|
||||
const int barWidth = pageWidth - 100;
|
||||
@ -198,15 +198,15 @@ void OpdsBookBrowserActivity::render() const {
|
||||
|
||||
// Browsing state
|
||||
// Show appropriate button hint based on selected entry type
|
||||
const char* confirmLabel = "Open";
|
||||
const char* confirmLabel = "Ouvrir";
|
||||
if (!entries.empty() && entries[selectorIndex].type == OpdsEntryType::BOOK) {
|
||||
confirmLabel = "Download";
|
||||
confirmLabel = "Télécharger";
|
||||
}
|
||||
const auto labels = mappedInput.mapLabels("« Back", confirmLabel, "", "");
|
||||
const auto labels = mappedInput.mapLabels("« Retour", confirmLabel, "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
|
||||
if (entries.empty()) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, "No entries found");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, "Aucune entrée trouvée");
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
@ -241,18 +241,18 @@ void OpdsBookBrowserActivity::fetchFeed(const std::string& path) {
|
||||
const char* serverUrl = SETTINGS.opdsServerUrl;
|
||||
if (strlen(serverUrl) == 0) {
|
||||
state = BrowserState::ERROR;
|
||||
errorMessage = "No server URL configured";
|
||||
errorMessage = "Aucun URL serveur configuré";
|
||||
updateRequired = true;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string url = UrlUtils::buildUrl(serverUrl, path);
|
||||
Serial.printf("[%lu] [OPDS] Fetching: %s\n", millis(), url.c_str());
|
||||
Serial.printf("[%lu] [OPDS] Récupération: %s\n", millis(), url.c_str());
|
||||
|
||||
std::string content;
|
||||
if (!HttpDownloader::fetchUrl(url, content)) {
|
||||
state = BrowserState::ERROR;
|
||||
errorMessage = "Failed to fetch feed";
|
||||
errorMessage = "Récupération du flux échouée";
|
||||
updateRequired = true;
|
||||
return;
|
||||
}
|
||||
@ -260,7 +260,7 @@ void OpdsBookBrowserActivity::fetchFeed(const std::string& path) {
|
||||
OpdsParser parser;
|
||||
if (!parser.parse(content.c_str(), content.size())) {
|
||||
state = BrowserState::ERROR;
|
||||
errorMessage = "Failed to parse feed";
|
||||
errorMessage = "Analyse du flux échouée";
|
||||
updateRequired = true;
|
||||
return;
|
||||
}
|
||||
@ -270,7 +270,7 @@ void OpdsBookBrowserActivity::fetchFeed(const std::string& path) {
|
||||
|
||||
if (entries.empty()) {
|
||||
state = BrowserState::ERROR;
|
||||
errorMessage = "No entries found";
|
||||
errorMessage = "Aucune entrée trouvée";
|
||||
updateRequired = true;
|
||||
return;
|
||||
}
|
||||
@ -285,7 +285,7 @@ void OpdsBookBrowserActivity::navigateToEntry(const OpdsEntry& entry) {
|
||||
currentPath = entry.href;
|
||||
|
||||
state = BrowserState::LOADING;
|
||||
statusMessage = "Loading...";
|
||||
statusMessage = "Chargement...";
|
||||
entries.clear();
|
||||
selectorIndex = 0;
|
||||
updateRequired = true;
|
||||
@ -303,7 +303,7 @@ void OpdsBookBrowserActivity::navigateBack() {
|
||||
navigationHistory.pop_back();
|
||||
|
||||
state = BrowserState::LOADING;
|
||||
statusMessage = "Loading...";
|
||||
statusMessage = "Chargement...";
|
||||
entries.clear();
|
||||
selectorIndex = 0;
|
||||
updateRequired = true;
|
||||
@ -329,7 +329,7 @@ void OpdsBookBrowserActivity::downloadBook(const OpdsEntry& book) {
|
||||
}
|
||||
std::string filename = "/" + StringUtils::sanitizeFilename(baseName) + ".epub";
|
||||
|
||||
Serial.printf("[%lu] [OPDS] Downloading: %s -> %s\n", millis(), downloadUrl.c_str(), filename.c_str());
|
||||
Serial.printf("[%lu] [OPDS] Téléchargement: %s -> %s\n", millis(), downloadUrl.c_str(), filename.c_str());
|
||||
|
||||
const auto result =
|
||||
HttpDownloader::downloadToFile(downloadUrl, filename, [this](const size_t downloaded, const size_t total) {
|
||||
@ -339,12 +339,12 @@ void OpdsBookBrowserActivity::downloadBook(const OpdsEntry& book) {
|
||||
});
|
||||
|
||||
if (result == HttpDownloader::OK) {
|
||||
Serial.printf("[%lu] [OPDS] Download complete: %s\n", millis(), filename.c_str());
|
||||
Serial.printf("[%lu] [OPDS] Téléchargement terminé: %s\n", millis(), filename.c_str());
|
||||
state = BrowserState::BROWSING;
|
||||
updateRequired = true;
|
||||
} else {
|
||||
state = BrowserState::ERROR;
|
||||
errorMessage = "Download failed";
|
||||
errorMessage = "Téléchargement échoué";
|
||||
updateRequired = true;
|
||||
}
|
||||
}
|
||||
@ -353,21 +353,21 @@ void OpdsBookBrowserActivity::checkAndConnectWifi() {
|
||||
// Already connected?
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
state = BrowserState::LOADING;
|
||||
statusMessage = "Loading...";
|
||||
statusMessage = "Chargement...";
|
||||
updateRequired = true;
|
||||
fetchFeed(currentPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to connect using saved credentials
|
||||
statusMessage = "Connecting to WiFi...";
|
||||
statusMessage = "Connexion au WiFi...";
|
||||
updateRequired = true;
|
||||
|
||||
WIFI_STORE.loadFromFile();
|
||||
const auto& credentials = WIFI_STORE.getCredentials();
|
||||
if (credentials.empty()) {
|
||||
state = BrowserState::ERROR;
|
||||
errorMessage = "No WiFi credentials saved";
|
||||
errorMessage = "Aucun identifiants sauvegardés";
|
||||
updateRequired = true;
|
||||
return;
|
||||
}
|
||||
@ -385,14 +385,14 @@ void OpdsBookBrowserActivity::checkAndConnectWifi() {
|
||||
}
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.printf("[%lu] [OPDS] WiFi connected: %s\n", millis(), WiFi.localIP().toString().c_str());
|
||||
Serial.printf("[%lu] [OPDS] WiFi connecté: %s\n", millis(), WiFi.localIP().toString().c_str());
|
||||
state = BrowserState::LOADING;
|
||||
statusMessage = "Loading...";
|
||||
statusMessage = "Chargement...";
|
||||
updateRequired = true;
|
||||
fetchFeed(currentPath);
|
||||
} else {
|
||||
state = BrowserState::ERROR;
|
||||
errorMessage = "WiFi connection failed";
|
||||
errorMessage = "Connexion WiFi échouée";
|
||||
updateRequired = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,21 +277,21 @@ void HomeActivity::render() const {
|
||||
}
|
||||
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, bookY + bookHeight - renderer.getLineHeight(UI_10_FONT_ID) * 3 / 2,
|
||||
"Continue Reading", !bookSelected);
|
||||
"Continuer la lecture", !bookSelected);
|
||||
} else {
|
||||
// No book to continue reading
|
||||
const int y =
|
||||
bookY + (bookHeight - renderer.getLineHeight(UI_12_FONT_ID) - renderer.getLineHeight(UI_10_FONT_ID)) / 2;
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, y, "No open book");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, y + renderer.getLineHeight(UI_12_FONT_ID), "Start reading below");
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, y, "Aucun livre ouvert");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, y + renderer.getLineHeight(UI_12_FONT_ID), "Commencer la lecture au-dessous");
|
||||
}
|
||||
|
||||
// --- Bottom menu tiles ---
|
||||
// Build menu items dynamically
|
||||
std::vector<const char*> menuItems = {"Browse Files", "File Transfer", "Settings"};
|
||||
std::vector<const char*> menuItems = {"Parcourir les fichiers", "Transfert de fichiers", "Paramètres"};
|
||||
if (hasOpdsUrl) {
|
||||
// Insert Calibre Library after Browse Files
|
||||
menuItems.insert(menuItems.begin() + 1, "Calibre Library");
|
||||
menuItems.insert(menuItems.begin() + 1, "Blibliothèque Calibre");
|
||||
}
|
||||
|
||||
const int menuTileWidth = pageWidth - 2 * margin;
|
||||
@ -329,7 +329,7 @@ void HomeActivity::render() const {
|
||||
renderer.drawText(UI_10_FONT_ID, textX, textY, label, !selected);
|
||||
}
|
||||
|
||||
const auto labels = mappedInput.mapLabels("", "Confirm", "Up", "Down");
|
||||
const auto labels = mappedInput.mapLabels("", "Confirmer", "Haut", "Bas");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
|
||||
const auto batteryX = pageWidth - 25 - renderer.getTextWidth(SMALL_FONT_ID, "100 %");
|
||||
|
||||
@ -34,7 +34,7 @@ void CalibreWirelessActivity::onEnter() {
|
||||
stateMutex = xSemaphoreCreateMutex();
|
||||
|
||||
state = WirelessState::DISCOVERING;
|
||||
statusMessage = "Discovering Calibre...";
|
||||
statusMessage = "Recherche de Calibre...";
|
||||
errorMessage.clear();
|
||||
calibreHostname.clear();
|
||||
calibreHost.clear();
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
namespace {
|
||||
// AP Mode configuration
|
||||
constexpr const char* AP_SSID = "CrossPoint-Reader";
|
||||
constexpr const char* AP_SSID = "CrossPoint-Liseuse";
|
||||
constexpr const char* AP_PASSWORD = nullptr; // Open network for ease of use
|
||||
constexpr const char* AP_HOSTNAME = "crosspoint";
|
||||
constexpr uint8_t AP_CHANNEL = 1;
|
||||
@ -34,7 +34,7 @@ void CrossPointWebServerActivity::taskTrampoline(void* param) {
|
||||
void CrossPointWebServerActivity::onEnter() {
|
||||
ActivityWithSubactivity::onEnter();
|
||||
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Free heap at onEnter: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Pile libre à onEnter: %d octets\n", millis(), ESP.getFreeHeap());
|
||||
|
||||
renderingMutex = xSemaphoreCreateMutex();
|
||||
|
||||
@ -55,7 +55,7 @@ void CrossPointWebServerActivity::onEnter() {
|
||||
);
|
||||
|
||||
// Launch network mode selection subactivity
|
||||
Serial.printf("[%lu] [WEBACT] Launching NetworkModeSelectionActivity...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Lancement de NetworkModeSelectionActivity...\n", millis());
|
||||
enterNewActivity(new NetworkModeSelectionActivity(
|
||||
renderer, mappedInput, [this](const NetworkMode mode) { onNetworkModeSelected(mode); },
|
||||
[this]() { onGoBack(); } // Cancel goes back to home
|
||||
@ -65,7 +65,7 @@ void CrossPointWebServerActivity::onEnter() {
|
||||
void CrossPointWebServerActivity::onExit() {
|
||||
ActivityWithSubactivity::onExit();
|
||||
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Free heap at onExit start: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Pile libre au début de onExit: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
|
||||
state = WebServerActivityState::SHUTTING_DOWN;
|
||||
|
||||
@ -77,56 +77,56 @@ void CrossPointWebServerActivity::onExit() {
|
||||
|
||||
// Stop DNS server if running (AP mode)
|
||||
if (dnsServer) {
|
||||
Serial.printf("[%lu] [WEBACT] Stopping DNS server...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Arrêt du serveur DNS...\n", millis());
|
||||
dnsServer->stop();
|
||||
delete dnsServer;
|
||||
dnsServer = nullptr;
|
||||
}
|
||||
|
||||
// CRITICAL: Wait for LWIP stack to flush any pending packets
|
||||
Serial.printf("[%lu] [WEBACT] Waiting 500ms for network stack to flush pending packets...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Attente de 500ms de pile réseau pour vider les paquets en attente...\n", millis());
|
||||
delay(500);
|
||||
|
||||
// Disconnect WiFi gracefully
|
||||
if (isApMode) {
|
||||
Serial.printf("[%lu] [WEBACT] Stopping WiFi AP...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Arrêt du WiFi AP...\n", millis());
|
||||
WiFi.softAPdisconnect(true);
|
||||
} else {
|
||||
Serial.printf("[%lu] [WEBACT] Disconnecting WiFi (graceful)...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Déconnexion du WiFi (gracieuse)...\n", millis());
|
||||
WiFi.disconnect(false); // false = don't erase credentials, send disconnect frame
|
||||
}
|
||||
delay(100); // Allow disconnect frame to be sent
|
||||
|
||||
Serial.printf("[%lu] [WEBACT] Setting WiFi mode OFF...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Désactivation du WiFi...\n", millis());
|
||||
WiFi.mode(WIFI_OFF);
|
||||
delay(100); // Allow WiFi hardware to fully power down
|
||||
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Free heap after WiFi disconnect: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Pile libre après déconnexion du WiFi: %d octets\n", millis(), ESP.getFreeHeap());
|
||||
|
||||
// Acquire mutex before deleting task
|
||||
Serial.printf("[%lu] [WEBACT] Acquiring rendering mutex before task deletion...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Acquisition du mutex de rendu avant la suppression de la tâche...\n", millis());
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
|
||||
// Delete the display task
|
||||
Serial.printf("[%lu] [WEBACT] Deleting display task...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Suppression de la tâche d'affichage...\n", millis());
|
||||
if (displayTaskHandle) {
|
||||
vTaskDelete(displayTaskHandle);
|
||||
displayTaskHandle = nullptr;
|
||||
Serial.printf("[%lu] [WEBACT] Display task deleted\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Tâche d'affichage supprimée\n", millis());
|
||||
}
|
||||
|
||||
// Delete the mutex
|
||||
Serial.printf("[%lu] [WEBACT] Deleting mutex...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Suppression du mutex...\n", millis());
|
||||
vSemaphoreDelete(renderingMutex);
|
||||
renderingMutex = nullptr;
|
||||
Serial.printf("[%lu] [WEBACT] Mutex deleted\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Mutex supprimé\n", millis());
|
||||
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Free heap at onExit end: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Pile libre à la fin de onExit: %d octets\n", millis(), ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
void CrossPointWebServerActivity::onNetworkModeSelected(const NetworkMode mode) {
|
||||
Serial.printf("[%lu] [WEBACT] Network mode selected: %s\n", millis(),
|
||||
mode == NetworkMode::JOIN_NETWORK ? "Join Network" : "Create Hotspot");
|
||||
Serial.printf("[%lu] [WEBACT] Mode de réseau selectionné: %s\n", millis(),
|
||||
mode == NetworkMode::JOIN_NETWORK ? "Réjoindre le réseau" : "Créer un point d'accès");
|
||||
|
||||
networkMode = mode;
|
||||
isApMode = (mode == NetworkMode::CREATE_HOTSPOT);
|
||||
@ -136,11 +136,11 @@ void CrossPointWebServerActivity::onNetworkModeSelected(const NetworkMode mode)
|
||||
|
||||
if (mode == NetworkMode::JOIN_NETWORK) {
|
||||
// STA mode - launch WiFi selection
|
||||
Serial.printf("[%lu] [WEBACT] Turning on WiFi (STA mode)...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Lancement du WiFi (Mode STA)...\n", millis());
|
||||
WiFi.mode(WIFI_STA);
|
||||
|
||||
state = WebServerActivityState::WIFI_SELECTION;
|
||||
Serial.printf("[%lu] [WEBACT] Launching WifiSelectionActivity...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Lancement de WifiSelectionActivity...\n", millis());
|
||||
enterNewActivity(new WifiSelectionActivity(renderer, mappedInput,
|
||||
[this](const bool connected) { onWifiSelectionComplete(connected); }));
|
||||
} else {
|
||||
@ -152,7 +152,7 @@ void CrossPointWebServerActivity::onNetworkModeSelected(const NetworkMode mode)
|
||||
}
|
||||
|
||||
void CrossPointWebServerActivity::onWifiSelectionComplete(const bool connected) {
|
||||
Serial.printf("[%lu] [WEBACT] WifiSelectionActivity completed, connected=%d\n", millis(), connected);
|
||||
Serial.printf("[%lu] [WEBACT] WifiSelectionActivity terminé, connecté=%d\n", millis(), connected);
|
||||
|
||||
if (connected) {
|
||||
// Get connection info before exiting subactivity
|
||||
@ -164,7 +164,7 @@ void CrossPointWebServerActivity::onWifiSelectionComplete(const bool connected)
|
||||
|
||||
// Start mDNS for hostname resolution
|
||||
if (MDNS.begin(AP_HOSTNAME)) {
|
||||
Serial.printf("[%lu] [WEBACT] mDNS started: http://%s.local/\n", millis(), AP_HOSTNAME);
|
||||
Serial.printf("[%lu] [WEBACT] mDNS lancé: http://%s.local/\n", millis(), AP_HOSTNAME);
|
||||
}
|
||||
|
||||
// Start the web server
|
||||
@ -180,8 +180,8 @@ void CrossPointWebServerActivity::onWifiSelectionComplete(const bool connected)
|
||||
}
|
||||
|
||||
void CrossPointWebServerActivity::startAccessPoint() {
|
||||
Serial.printf("[%lu] [WEBACT] Starting Access Point mode...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Free heap before AP start: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
Serial.printf("[%lu] [WEBACT] Lancement du mode Access Point...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Pile libre avant le début de AP: %d octets\n", millis(), ESP.getFreeHeap());
|
||||
|
||||
// Configure and start the AP
|
||||
WiFi.mode(WIFI_AP);
|
||||
@ -197,7 +197,7 @@ void CrossPointWebServerActivity::startAccessPoint() {
|
||||
}
|
||||
|
||||
if (!apStarted) {
|
||||
Serial.printf("[%lu] [WEBACT] ERROR: Failed to start Access Point!\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] ERROR: Lancement de Access Point échoué!\n", millis());
|
||||
onGoBack();
|
||||
return;
|
||||
}
|
||||
@ -211,15 +211,15 @@ void CrossPointWebServerActivity::startAccessPoint() {
|
||||
connectedIP = ipStr;
|
||||
connectedSSID = AP_SSID;
|
||||
|
||||
Serial.printf("[%lu] [WEBACT] Access Point started!\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Access Point lancé!\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] SSID: %s\n", millis(), AP_SSID);
|
||||
Serial.printf("[%lu] [WEBACT] IP: %s\n", millis(), connectedIP.c_str());
|
||||
|
||||
// Start mDNS for hostname resolution
|
||||
if (MDNS.begin(AP_HOSTNAME)) {
|
||||
Serial.printf("[%lu] [WEBACT] mDNS started: http://%s.local/\n", millis(), AP_HOSTNAME);
|
||||
Serial.printf("[%lu] [WEBACT] mDNS lancé: http://%s.local/\n", millis(), AP_HOSTNAME);
|
||||
} else {
|
||||
Serial.printf("[%lu] [WEBACT] WARNING: mDNS failed to start\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] ATTENTION: lancement de mDNS échoué\n", millis());
|
||||
}
|
||||
|
||||
// Start DNS server for captive portal behavior
|
||||
@ -227,16 +227,16 @@ void CrossPointWebServerActivity::startAccessPoint() {
|
||||
dnsServer = new DNSServer();
|
||||
dnsServer->setErrorReplyCode(DNSReplyCode::NoError);
|
||||
dnsServer->start(DNS_PORT, "*", apIP);
|
||||
Serial.printf("[%lu] [WEBACT] DNS server started for captive portal\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Serveur DNS lancé pour portail captif\n", millis());
|
||||
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Free heap after AP start: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
Serial.printf("[%lu] [WEBACT] [MEM] Pile libre après lancement de AP: %d octets\n", millis(), ESP.getFreeHeap());
|
||||
|
||||
// Start the web server
|
||||
startWebServer();
|
||||
}
|
||||
|
||||
void CrossPointWebServerActivity::startWebServer() {
|
||||
Serial.printf("[%lu] [WEBACT] Starting web server...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Lancement du server web...\n", millis());
|
||||
|
||||
// Create the web server instance
|
||||
webServer.reset(new CrossPointWebServer());
|
||||
@ -244,16 +244,16 @@ void CrossPointWebServerActivity::startWebServer() {
|
||||
|
||||
if (webServer->isRunning()) {
|
||||
state = WebServerActivityState::SERVER_RUNNING;
|
||||
Serial.printf("[%lu] [WEBACT] Web server started successfully\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Serveur web lancé avec succès!\n", millis());
|
||||
|
||||
// Force an immediate render since we're transitioning from a subactivity
|
||||
// that had its own rendering task. We need to make sure our display is shown.
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
render();
|
||||
xSemaphoreGive(renderingMutex);
|
||||
Serial.printf("[%lu] [WEBACT] Rendered File Transfer screen\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Écran File Transfer rendu\n", millis());
|
||||
} else {
|
||||
Serial.printf("[%lu] [WEBACT] ERROR: Failed to start web server!\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] ERREUR: Lancement du serveur web échoué!\n", millis());
|
||||
webServer.reset();
|
||||
// Go back on error
|
||||
onGoBack();
|
||||
@ -262,9 +262,9 @@ void CrossPointWebServerActivity::startWebServer() {
|
||||
|
||||
void CrossPointWebServerActivity::stopWebServer() {
|
||||
if (webServer && webServer->isRunning()) {
|
||||
Serial.printf("[%lu] [WEBACT] Stopping web server...\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Arrêt du serveur web...\n", millis());
|
||||
webServer->stop();
|
||||
Serial.printf("[%lu] [WEBACT] Web server stopped\n", millis());
|
||||
Serial.printf("[%lu] [WEBACT] Serveur web arrêté\n", millis());
|
||||
}
|
||||
webServer.reset();
|
||||
}
|
||||
@ -290,7 +290,7 @@ void CrossPointWebServerActivity::loop() {
|
||||
|
||||
// Log if there's a significant gap between handleClient calls (>100ms)
|
||||
if (lastHandleClientTime > 0 && timeSinceLastHandleClient > 100) {
|
||||
Serial.printf("[%lu] [WEBACT] WARNING: %lu ms gap since last handleClient\n", millis(),
|
||||
Serial.printf("[%lu] [WEBACT] ATTENTION: %lu ms intervalle depuis le dernier handleClient\n", millis(),
|
||||
timeSinceLastHandleClient);
|
||||
}
|
||||
|
||||
@ -334,7 +334,7 @@ void CrossPointWebServerActivity::render() const {
|
||||
} else if (state == WebServerActivityState::AP_STARTING) {
|
||||
renderer.clearScreen();
|
||||
const auto pageHeight = renderer.getScreenHeight();
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, pageHeight / 2 - 20, "Starting Hotspot...", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, pageHeight / 2 - 20, "Lancement du point d'accès...", true, EpdFontFamily::BOLD);
|
||||
renderer.displayBuffer();
|
||||
}
|
||||
}
|
||||
@ -344,7 +344,7 @@ void drawQRCode(const GfxRenderer& renderer, const int x, const int y, const std
|
||||
// The structure to manage the QR code
|
||||
QRCode qrcode;
|
||||
uint8_t qrcodeBytes[qrcode_getBufferSize(4)];
|
||||
Serial.printf("[%lu] [WEBACT] QR Code (%lu): %s\n", millis(), data.length(), data.c_str());
|
||||
Serial.printf("[%lu] [WEBACT] Code QR (%lu): %s\n", millis(), data.length(), data.c_str());
|
||||
|
||||
qrcode_initText(&qrcode, qrcodeBytes, 4, ECC_LOW, data.c_str());
|
||||
const uint8_t px = 6; // pixels per module
|
||||
@ -365,21 +365,21 @@ void CrossPointWebServerActivity::renderServerRunning() const {
|
||||
// Use consistent line spacing
|
||||
constexpr int LINE_SPACING = 28; // Space between lines
|
||||
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Transfert de fichiers", true, EpdFontFamily::BOLD);
|
||||
|
||||
if (isApMode) {
|
||||
// AP mode display - center the content block
|
||||
int startY = 55;
|
||||
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, startY, "Hotspot Mode", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, startY, "Mode de point d'accès", true, EpdFontFamily::BOLD);
|
||||
|
||||
std::string ssidInfo = "Network: " + connectedSSID;
|
||||
std::string ssidInfo = "Réseau: " + connectedSSID;
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING, ssidInfo.c_str());
|
||||
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 2, "Connect your device to this WiFi network");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 2, "Connectez votre appareil à ce réseau");
|
||||
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3,
|
||||
"or scan QR code with your phone to connect to Wifi.");
|
||||
"ou scannez le code QR avec votre cellulaire pour connecter au WiFi.");
|
||||
// Show QR code for URL
|
||||
const std::string wifiConfig = std::string("WIFI:S:") + connectedSSID + ";;";
|
||||
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 4, wifiConfig);
|
||||
@ -390,24 +390,24 @@ void CrossPointWebServerActivity::renderServerRunning() const {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, EpdFontFamily::BOLD);
|
||||
|
||||
// Show IP address as fallback
|
||||
std::string ipUrl = "or http://" + connectedIP + "/";
|
||||
std::string ipUrl = "ou http://" + connectedIP + "/";
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, ipUrl.c_str());
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "Open this URL in your browser");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "Ouvrez cet URL dans votre navigateur");
|
||||
|
||||
// Show QR code for URL
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 6, "or scan QR code with your phone:");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 6, "ou scannez le code QR avec votre cellulaire:");
|
||||
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 7, hostnameUrl);
|
||||
} else {
|
||||
// STA mode display (original behavior)
|
||||
const int startY = 65;
|
||||
|
||||
std::string ssidInfo = "Network: " + connectedSSID;
|
||||
std::string ssidInfo = "Réseau: " + connectedSSID;
|
||||
if (ssidInfo.length() > 28) {
|
||||
ssidInfo.replace(25, ssidInfo.length() - 25, "...");
|
||||
}
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, startY, ssidInfo.c_str());
|
||||
|
||||
std::string ipInfo = "IP Address: " + connectedIP;
|
||||
std::string ipInfo = "Adresse IP: " + connectedIP;
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING, ipInfo.c_str());
|
||||
|
||||
// Show web server URL prominently
|
||||
@ -415,16 +415,16 @@ void CrossPointWebServerActivity::renderServerRunning() const {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, startY + LINE_SPACING * 2, webInfo.c_str(), true, EpdFontFamily::BOLD);
|
||||
|
||||
// Also show hostname URL
|
||||
std::string hostnameUrl = std::string("or http://") + AP_HOSTNAME + ".local/";
|
||||
std::string hostnameUrl = std::string("ou http://") + AP_HOSTNAME + ".local/";
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str());
|
||||
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, "Open this URL in your browser");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, "Ouvrez cet URL dans votre navigateur");
|
||||
|
||||
// Show QR code for URL
|
||||
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 6, webInfo);
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "or scan QR code with your phone:");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "ou scannez le code QR avec votre cellulaire:");
|
||||
}
|
||||
|
||||
const auto labels = mappedInput.mapLabels("« Exit", "", "", "");
|
||||
const auto labels = mappedInput.mapLabels("« Sortie", "", "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
}
|
||||
|
||||
@ -7,9 +7,9 @@
|
||||
|
||||
namespace {
|
||||
constexpr int MENU_ITEM_COUNT = 2;
|
||||
const char* MENU_ITEMS[MENU_ITEM_COUNT] = {"Join a Network", "Create Hotspot"};
|
||||
const char* MENU_DESCRIPTIONS[MENU_ITEM_COUNT] = {"Connect to an existing WiFi network",
|
||||
"Create a WiFi network others can join"};
|
||||
const char* MENU_ITEMS[MENU_ITEM_COUNT] = {"Réjoindre un réseau", "Créer un point d'accès"};
|
||||
const char* MENU_DESCRIPTIONS[MENU_ITEM_COUNT] = {"Connecter à un réseau WiFi existant",
|
||||
"Créez un réseau Wi-Fi auquel d'autres peuvent se connecter"};
|
||||
} // namespace
|
||||
|
||||
void NetworkModeSelectionActivity::taskTrampoline(void* param) {
|
||||
@ -97,10 +97,10 @@ void NetworkModeSelectionActivity::render() const {
|
||||
const auto pageHeight = renderer.getScreenHeight();
|
||||
|
||||
// Draw header
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "File Transfer", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Transfert de fichiers", true, EpdFontFamily::BOLD);
|
||||
|
||||
// Draw subtitle
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 50, "How would you like to connect?");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 50, "Comment voulez-vous connecter?");
|
||||
|
||||
// Draw menu items centered on screen
|
||||
constexpr int itemHeight = 50; // Height for each menu item (including description)
|
||||
@ -122,7 +122,7 @@ void NetworkModeSelectionActivity::render() const {
|
||||
}
|
||||
|
||||
// Draw help text at bottom
|
||||
const auto labels = mappedInput.mapLabels("« Back", "Select", "", "");
|
||||
const auto labels = mappedInput.mapLabels("« Retour", "Select.", "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
|
||||
renderer.displayBuffer();
|
||||
|
||||
@ -54,36 +54,36 @@ void WifiSelectionActivity::onEnter() {
|
||||
void WifiSelectionActivity::onExit() {
|
||||
Activity::onExit();
|
||||
|
||||
Serial.printf("[%lu] [WIFI] [MEM] Free heap at onExit start: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
Serial.printf("[%lu] [WIFI] [MEM] Pile libre au début de onExit: %d octets\n", millis(), ESP.getFreeHeap());
|
||||
|
||||
// Stop any ongoing WiFi scan
|
||||
Serial.printf("[%lu] [WIFI] Deleting WiFi scan...\n", millis());
|
||||
Serial.printf("[%lu] [WIFI] Suppression du scan WiFi...\n", millis());
|
||||
WiFi.scanDelete();
|
||||
Serial.printf("[%lu] [WIFI] [MEM] Free heap after scanDelete: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
Serial.printf("[%lu] [WIFI] [MEM] Pile libre après scanDelete: %d octets\n", millis(), ESP.getFreeHeap());
|
||||
|
||||
// Note: We do NOT disconnect WiFi here - the parent activity (CrossPointWebServerActivity)
|
||||
// manages WiFi connection state. We just clean up the scan and task.
|
||||
|
||||
// Acquire mutex before deleting task to ensure task isn't using it
|
||||
// This prevents hangs/crashes if the task holds the mutex when deleted
|
||||
Serial.printf("[%lu] [WIFI] Acquiring rendering mutex before task deletion...\n", millis());
|
||||
Serial.printf("[%lu] [WIFI] Acquisition du mutex de rendu avant la suppression de la tâche...\n", millis());
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
|
||||
// Delete the display task (we now hold the mutex, so task is blocked if it needs it)
|
||||
Serial.printf("[%lu] [WIFI] Deleting display task...\n", millis());
|
||||
Serial.printf("[%lu] [WIFI] Suppression de la tâche d'affichage...\n", millis());
|
||||
if (displayTaskHandle) {
|
||||
vTaskDelete(displayTaskHandle);
|
||||
displayTaskHandle = nullptr;
|
||||
Serial.printf("[%lu] [WIFI] Display task deleted\n", millis());
|
||||
Serial.printf("[%lu] [WIFI] Tâche d'affichage supprimée\n", millis());
|
||||
}
|
||||
|
||||
// Now safe to delete the mutex since we own it
|
||||
Serial.printf("[%lu] [WIFI] Deleting mutex...\n", millis());
|
||||
Serial.printf("[%lu] [WIFI] Suppression de mutex...\n", millis());
|
||||
vSemaphoreDelete(renderingMutex);
|
||||
renderingMutex = nullptr;
|
||||
Serial.printf("[%lu] [WIFI] Mutex deleted\n", millis());
|
||||
Serial.printf("[%lu] [WIFI] Mutex supprimé\n", millis());
|
||||
|
||||
Serial.printf("[%lu] [WIFI] [MEM] Free heap at onExit end: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
Serial.printf("[%lu] [WIFI] [MEM] Pile libre à la fin de onExit: %d octets\n", millis(), ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
void WifiSelectionActivity::startWifiScan() {
|
||||
@ -179,7 +179,7 @@ void WifiSelectionActivity::selectNetwork(const int index) {
|
||||
// Use saved password - connect directly
|
||||
enteredPassword = savedCred->password;
|
||||
usedSavedPassword = true;
|
||||
Serial.printf("[%lu] [WiFi] Using saved password for %s, length: %zu\n", millis(), selectedSSID.c_str(),
|
||||
Serial.printf("[%lu] [WiFi] Utilisation du mot de passe sauvegardé pour %s, longueur: %zu\n", millis(), selectedSSID.c_str(),
|
||||
enteredPassword.size());
|
||||
attemptConnection();
|
||||
return;
|
||||
@ -191,7 +191,7 @@ void WifiSelectionActivity::selectNetwork(const int index) {
|
||||
// Don't allow screen updates while changing activity
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
enterNewActivity(new KeyboardEntryActivity(
|
||||
renderer, mappedInput, "Enter WiFi Password",
|
||||
renderer, mappedInput, "Entrez le mot de passe du WiFi",
|
||||
"", // No initial text
|
||||
50, // Y position
|
||||
64, // Max password length
|
||||
@ -251,16 +251,16 @@ void WifiSelectionActivity::checkConnectionStatus() {
|
||||
updateRequired = true;
|
||||
} else {
|
||||
// Using saved password or open network - complete immediately
|
||||
Serial.printf("[%lu] [WIFI] Connected with saved/open credentials, completing immediately\n", millis());
|
||||
Serial.printf("[%lu] [WIFI] Connecté avec les identifiants sauvegardés/ouverts, complétion immédiate\n", millis());
|
||||
onComplete(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == WL_CONNECT_FAILED || status == WL_NO_SSID_AVAIL) {
|
||||
connectionError = "Connection failed";
|
||||
connectionError = "Connexion échouée";
|
||||
if (status == WL_NO_SSID_AVAIL) {
|
||||
connectionError = "Network not found";
|
||||
connectionError = "Réseau introuvable";
|
||||
}
|
||||
state = WifiSelectionState::CONNECTION_FAILED;
|
||||
updateRequired = true;
|
||||
@ -505,14 +505,14 @@ void WifiSelectionActivity::renderNetworkList() const {
|
||||
const auto pageHeight = renderer.getScreenHeight();
|
||||
|
||||
// Draw header
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "WiFi Networks", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Réseaux WiFi", true, EpdFontFamily::BOLD);
|
||||
|
||||
if (networks.empty()) {
|
||||
// No networks found or scan failed
|
||||
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
||||
const auto top = (pageHeight - height) / 2;
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top, "No networks found");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, top + height + 10, "Press OK to scan again");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top, "Aucun réseau trouvé");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, top + height + 10, "Appuyez OK pour scanner à nouveau");
|
||||
} else {
|
||||
// Calculate how many networks we can display
|
||||
constexpr int startY = 60;
|
||||
@ -568,13 +568,13 @@ void WifiSelectionActivity::renderNetworkList() const {
|
||||
|
||||
// Show network count
|
||||
char countStr[32];
|
||||
snprintf(countStr, sizeof(countStr), "%zu networks found", networks.size());
|
||||
snprintf(countStr, sizeof(countStr), "%zu réseaux trouvés", networks.size());
|
||||
renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 90, countStr);
|
||||
}
|
||||
|
||||
// Draw help text
|
||||
renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 75, "* = Encrypted | + = Saved");
|
||||
const auto labels = mappedInput.mapLabels("« Back", "Connect", "", "");
|
||||
renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 75, "* = Crypté | + = Sauvegardé");
|
||||
const auto labels = mappedInput.mapLabels("« Retour", "Connecter", "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
}
|
||||
|
||||
@ -584,9 +584,9 @@ void WifiSelectionActivity::renderConnecting() const {
|
||||
const auto top = (pageHeight - height) / 2;
|
||||
|
||||
if (state == WifiSelectionState::SCANNING) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top, "Scanning...");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top, "Recherche...");
|
||||
} else {
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connecting...", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connexion...", true, EpdFontFamily::BOLD);
|
||||
|
||||
std::string ssidInfo = "to " + selectedSSID;
|
||||
if (ssidInfo.length() > 25) {
|
||||
@ -601,18 +601,18 @@ void WifiSelectionActivity::renderConnected() const {
|
||||
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
||||
const auto top = (pageHeight - height * 4) / 2;
|
||||
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 30, "Connected!", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 30, "Connecté!", true, EpdFontFamily::BOLD);
|
||||
|
||||
std::string ssidInfo = "Network: " + selectedSSID;
|
||||
std::string ssidInfo = "Réseau: " + selectedSSID;
|
||||
if (ssidInfo.length() > 28) {
|
||||
ssidInfo.replace(25, ssidInfo.length() - 25, "...");
|
||||
}
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top + 10, ssidInfo.c_str());
|
||||
|
||||
const std::string ipInfo = "IP Address: " + connectedIP;
|
||||
const std::string ipInfo = "Adresse IP: " + connectedIP;
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top + 40, ipInfo.c_str());
|
||||
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Press any button to continue");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Appuyez sur n'importe quel bouton pour continuer");
|
||||
}
|
||||
|
||||
void WifiSelectionActivity::renderSavePrompt() const {
|
||||
@ -621,15 +621,15 @@ void WifiSelectionActivity::renderSavePrompt() const {
|
||||
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
||||
const auto top = (pageHeight - height * 3) / 2;
|
||||
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connected!", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connecté!", true, EpdFontFamily::BOLD);
|
||||
|
||||
std::string ssidInfo = "Network: " + selectedSSID;
|
||||
std::string ssidInfo = "Réseaux: " + selectedSSID;
|
||||
if (ssidInfo.length() > 28) {
|
||||
ssidInfo.replace(25, ssidInfo.length() - 25, "...");
|
||||
}
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top, ssidInfo.c_str());
|
||||
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top + 40, "Save password for next time?");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top + 40, "Enregistrer le mot de passe pour la prochaine fois?");
|
||||
|
||||
// Draw Yes/No buttons
|
||||
const int buttonY = top + 80;
|
||||
@ -640,19 +640,19 @@ void WifiSelectionActivity::renderSavePrompt() const {
|
||||
|
||||
// Draw "Yes" button
|
||||
if (savePromptSelection == 0) {
|
||||
renderer.drawText(UI_10_FONT_ID, startX, buttonY, "[Yes]");
|
||||
renderer.drawText(UI_10_FONT_ID, startX, buttonY, "[Oui]");
|
||||
} else {
|
||||
renderer.drawText(UI_10_FONT_ID, startX + 4, buttonY, "Yes");
|
||||
renderer.drawText(UI_10_FONT_ID, startX + 4, buttonY, "Oui");
|
||||
}
|
||||
|
||||
// Draw "No" button
|
||||
if (savePromptSelection == 1) {
|
||||
renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing, buttonY, "[No]");
|
||||
renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing, buttonY, "[Non]");
|
||||
} else {
|
||||
renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing + 4, buttonY, "No");
|
||||
renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing + 4, buttonY, "Non");
|
||||
}
|
||||
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "LEFT/RIGHT: Select | OK: Confirm");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "GAUCHE/DROITE: Selectionner | OK: Confirmer");
|
||||
}
|
||||
|
||||
void WifiSelectionActivity::renderConnectionFailed() const {
|
||||
@ -660,9 +660,9 @@ void WifiSelectionActivity::renderConnectionFailed() const {
|
||||
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
||||
const auto top = (pageHeight - height * 2) / 2;
|
||||
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 20, "Connection Failed", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 20, "Connexion échouée", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top + 20, connectionError.c_str());
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Press any button to continue");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Appuyez sur n'importe quel bouton pour continuer");
|
||||
}
|
||||
|
||||
void WifiSelectionActivity::renderForgetPrompt() const {
|
||||
@ -671,15 +671,15 @@ void WifiSelectionActivity::renderForgetPrompt() const {
|
||||
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
||||
const auto top = (pageHeight - height * 3) / 2;
|
||||
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Forget Network?", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Oublier le réseau?", true, EpdFontFamily::BOLD);
|
||||
|
||||
std::string ssidInfo = "Network: " + selectedSSID;
|
||||
std::string ssidInfo = "Réseau: " + selectedSSID;
|
||||
if (ssidInfo.length() > 28) {
|
||||
ssidInfo.replace(25, ssidInfo.length() - 25, "...");
|
||||
}
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top, ssidInfo.c_str());
|
||||
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top + 40, "Remove saved password?");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, top + 40, "Supprimer le mot de passe sauvegardé?");
|
||||
|
||||
// Draw Yes/No buttons
|
||||
const int buttonY = top + 80;
|
||||
@ -690,17 +690,17 @@ void WifiSelectionActivity::renderForgetPrompt() const {
|
||||
|
||||
// Draw "Yes" button
|
||||
if (forgetPromptSelection == 0) {
|
||||
renderer.drawText(UI_10_FONT_ID, startX, buttonY, "[Yes]");
|
||||
renderer.drawText(UI_10_FONT_ID, startX, buttonY, "[Oui]");
|
||||
} else {
|
||||
renderer.drawText(UI_10_FONT_ID, startX + 4, buttonY, "Yes");
|
||||
renderer.drawText(UI_10_FONT_ID, startX + 4, buttonY, "Oui");
|
||||
}
|
||||
|
||||
// Draw "No" button
|
||||
if (forgetPromptSelection == 1) {
|
||||
renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing, buttonY, "[No]");
|
||||
renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing, buttonY, "[Non]");
|
||||
} else {
|
||||
renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing + 4, buttonY, "No");
|
||||
renderer.drawText(UI_10_FONT_ID, startX + buttonWidth + buttonSpacing + 4, buttonY, "Non");
|
||||
}
|
||||
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "LEFT/RIGHT: Select | OK: Confirm");
|
||||
renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "GAUCHE/DROITE: Selectionner | OK: Confirmer");
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ void EpubReaderActivity::onEnter() {
|
||||
if (f.read(data, 4) == 4) {
|
||||
currentSpineIndex = data[0] + (data[1] << 8);
|
||||
nextPageNumber = data[2] + (data[3] << 8);
|
||||
Serial.printf("[%lu] [ERS] Loaded cache: %d, %d\n", millis(), currentSpineIndex, nextPageNumber);
|
||||
Serial.printf("[%lu] [ERS] Cache chargée: %d, %d\n", millis(), currentSpineIndex, nextPageNumber);
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
@ -69,7 +69,7 @@ void EpubReaderActivity::onEnter() {
|
||||
int textSpineIndex = epub->getSpineIndexForTextReference();
|
||||
if (textSpineIndex != 0) {
|
||||
currentSpineIndex = textSpineIndex;
|
||||
Serial.printf("[%lu] [ERS] Opened for first time, navigating to text reference at index %d\n", millis(),
|
||||
Serial.printf("[%lu] [ERS] Ouvert pour la première fois, navigation à la référence textuel à l'indice %d\n", millis(),
|
||||
textSpineIndex);
|
||||
}
|
||||
}
|
||||
@ -242,7 +242,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
// Show end of book screen
|
||||
if (currentSpineIndex == epub->getSpineItemsCount()) {
|
||||
renderer.clearScreen();
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 300, "End of book", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Fin du livre", true, EpdFontFamily::BOLD);
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
@ -258,7 +258,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
|
||||
if (!section) {
|
||||
const auto filepath = epub->getSpineItem(currentSpineIndex).href;
|
||||
Serial.printf("[%lu] [ERS] Loading file: %s, index: %d\n", millis(), filepath.c_str(), currentSpineIndex);
|
||||
Serial.printf("[%lu] [ERS] Chargement du fichier: %s, indice: %d\n", millis(), filepath.c_str(), currentSpineIndex);
|
||||
section = std::unique_ptr<Section>(new Section(epub, currentSpineIndex, renderer));
|
||||
|
||||
const uint16_t viewportWidth = renderer.getScreenWidth() - orientedMarginLeft - orientedMarginRight;
|
||||
@ -267,13 +267,13 @@ void EpubReaderActivity::renderScreen() {
|
||||
if (!section->loadSectionFile(SETTINGS.getReaderFontId(), SETTINGS.getReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, SETTINGS.paragraphAlignment, viewportWidth,
|
||||
viewportHeight)) {
|
||||
Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis());
|
||||
Serial.printf("[%lu] [ERS] Aucune cache trouvée, création...\n", millis());
|
||||
|
||||
// Progress bar dimensions
|
||||
constexpr int barWidth = 200;
|
||||
constexpr int barHeight = 10;
|
||||
constexpr int boxMargin = 20;
|
||||
const int textWidth = renderer.getTextWidth(UI_12_FONT_ID, "Indexing...");
|
||||
const int textWidth = renderer.getTextWidth(UI_12_FONT_ID, "Indexage...");
|
||||
const int boxWidthWithBar = (barWidth > textWidth ? barWidth : textWidth) + boxMargin * 2;
|
||||
const int boxWidthNoBar = textWidth + boxMargin * 2;
|
||||
const int boxHeightWithBar = renderer.getLineHeight(UI_12_FONT_ID) + barHeight + boxMargin * 3;
|
||||
@ -287,7 +287,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
// Always show "Indexing..." text first
|
||||
{
|
||||
renderer.fillRect(boxXNoBar, boxY, boxWidthNoBar, boxHeightNoBar, false);
|
||||
renderer.drawText(UI_12_FONT_ID, boxXNoBar + boxMargin, boxY + boxMargin, "Indexing...");
|
||||
renderer.drawText(UI_12_FONT_ID, boxXNoBar + boxMargin, boxY + boxMargin, "Indexage...");
|
||||
renderer.drawRect(boxXNoBar + 5, boxY + 5, boxWidthNoBar - 10, boxHeightNoBar - 10);
|
||||
renderer.displayBuffer();
|
||||
pagesUntilFullRefresh = 0;
|
||||
@ -296,7 +296,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
// Setup callback - only called for chapters >= 50KB, redraws with progress bar
|
||||
auto progressSetup = [this, boxXWithBar, boxWidthWithBar, boxHeightWithBar, barX, barY] {
|
||||
renderer.fillRect(boxXWithBar, boxY, boxWidthWithBar, boxHeightWithBar, false);
|
||||
renderer.drawText(UI_12_FONT_ID, boxXWithBar + boxMargin, boxY + boxMargin, "Indexing...");
|
||||
renderer.drawText(UI_12_FONT_ID, boxXWithBar + boxMargin, boxY + boxMargin, "Indexage...");
|
||||
renderer.drawRect(boxXWithBar + 5, boxY + 5, boxWidthWithBar - 10, boxHeightWithBar - 10);
|
||||
renderer.drawRect(barX, barY, barWidth, barHeight);
|
||||
renderer.displayBuffer();
|
||||
@ -312,12 +312,12 @@ void EpubReaderActivity::renderScreen() {
|
||||
if (!section->createSectionFile(SETTINGS.getReaderFontId(), SETTINGS.getReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, SETTINGS.paragraphAlignment, viewportWidth,
|
||||
viewportHeight, progressSetup, progressCallback)) {
|
||||
Serial.printf("[%lu] [ERS] Failed to persist page data to SD\n", millis());
|
||||
Serial.printf("[%lu] [ERS] Persistence des données de page au SD échouée\n", millis());
|
||||
section.reset();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Serial.printf("[%lu] [ERS] Cache found, skipping build...\n", millis());
|
||||
Serial.printf("[%lu] [ERS] Cache trouvée, sauter sa construction...\n", millis());
|
||||
}
|
||||
|
||||
if (nextPageNumber == UINT16_MAX) {
|
||||
@ -330,16 +330,16 @@ void EpubReaderActivity::renderScreen() {
|
||||
renderer.clearScreen();
|
||||
|
||||
if (section->pageCount == 0) {
|
||||
Serial.printf("[%lu] [ERS] No pages to render\n", millis());
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Empty chapter", true, EpdFontFamily::BOLD);
|
||||
Serial.printf("[%lu] [ERS] Aucune page à afficher\n", millis());
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Chapitre vide", true, EpdFontFamily::BOLD);
|
||||
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (section->currentPage < 0 || section->currentPage >= section->pageCount) {
|
||||
Serial.printf("[%lu] [ERS] Page out of bounds: %d (max %d)\n", millis(), section->currentPage, section->pageCount);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Out of bounds", true, EpdFontFamily::BOLD);
|
||||
Serial.printf("[%lu] [ERS] Page hors limites: %d (max %d)\n", millis(), section->currentPage, section->pageCount);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Hors limites", true, EpdFontFamily::BOLD);
|
||||
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
@ -348,14 +348,14 @@ void EpubReaderActivity::renderScreen() {
|
||||
{
|
||||
auto p = section->loadPageFromSectionFile();
|
||||
if (!p) {
|
||||
Serial.printf("[%lu] [ERS] Failed to load page from SD - clearing section cache\n", millis());
|
||||
Serial.printf("[%lu] [ERS] Chargment de page du SD échoué - suppression de la cache de section\n", millis());
|
||||
section->clearCache();
|
||||
section.reset();
|
||||
return renderScreen();
|
||||
}
|
||||
const auto start = millis();
|
||||
renderContents(std::move(p), orientedMarginTop, orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||
Serial.printf("[%lu] [ERS] Rendered page in %dms\n", millis(), millis() - start);
|
||||
Serial.printf("[%lu] [ERS] Page rendue en %dms\n", millis(), millis() - start);
|
||||
}
|
||||
|
||||
FsFile f;
|
||||
@ -451,8 +451,8 @@ void EpubReaderActivity::renderStatusBar(const int orientedMarginRight, const in
|
||||
std::string title;
|
||||
int titleWidth;
|
||||
if (tocIndex == -1) {
|
||||
title = "Unnamed";
|
||||
titleWidth = renderer.getTextWidth(SMALL_FONT_ID, "Unnamed");
|
||||
title = "Sans nom";
|
||||
titleWidth = renderer.getTextWidth(SMALL_FONT_ID, "Sans nom");
|
||||
} else {
|
||||
const auto tocItem = epub->getTocItem(tocIndex);
|
||||
title = tocItem.title;
|
||||
|
||||
@ -180,14 +180,14 @@ void FileSelectionActivity::render() const {
|
||||
renderer.clearScreen();
|
||||
|
||||
const auto pageWidth = renderer.getScreenWidth();
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Books", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Livres", true, EpdFontFamily::BOLD);
|
||||
|
||||
// Help text
|
||||
const auto labels = mappedInput.mapLabels("« Home", "Open", "", "");
|
||||
const auto labels = mappedInput.mapLabels("« Accueil", "Ouvrir", "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
|
||||
if (files.empty()) {
|
||||
renderer.drawText(UI_10_FONT_ID, 20, 60, "No books found");
|
||||
renderer.drawText(UI_10_FONT_ID, 20, 60, "Aucun livre trouvé");
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ bool ReaderActivity::isXtcFile(const std::string& path) {
|
||||
|
||||
std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) {
|
||||
if (!SdMan.exists(path.c_str())) {
|
||||
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
|
||||
Serial.printf("[%lu] [ ] Le fichier n'existe pas: %s\n", millis(), path.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -31,13 +31,13 @@ std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) {
|
||||
return epub;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [ ] Failed to load epub\n", millis());
|
||||
Serial.printf("[%lu] [ ] Chargement de l'epub échoué\n", millis());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Xtc> ReaderActivity::loadXtc(const std::string& path) {
|
||||
if (!SdMan.exists(path.c_str())) {
|
||||
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
|
||||
Serial.printf("[%lu] [ ] Le fichier n'existe pas: %s\n", millis(), path.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -46,14 +46,14 @@ std::unique_ptr<Xtc> ReaderActivity::loadXtc(const std::string& path) {
|
||||
return xtc;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [ ] Failed to load XTC\n", millis());
|
||||
Serial.printf("[%lu] [ ] Chargement du XTC échoué\n", millis());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ReaderActivity::onSelectBookFile(const std::string& path) {
|
||||
currentBookPath = path; // Track current book path
|
||||
exitActivity();
|
||||
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInput, "Loading..."));
|
||||
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInput, "Chargement..."));
|
||||
|
||||
if (isXtcFile(path)) {
|
||||
// Load XTC file
|
||||
@ -62,7 +62,7 @@ void ReaderActivity::onSelectBookFile(const std::string& path) {
|
||||
onGoToXtcReader(std::move(xtc));
|
||||
} else {
|
||||
exitActivity();
|
||||
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInput, "Failed to load XTC",
|
||||
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInput, "Chargement du XTC échoué",
|
||||
EpdFontFamily::REGULAR, EInkDisplay::HALF_REFRESH));
|
||||
delay(2000);
|
||||
onGoToFileSelection();
|
||||
@ -74,7 +74,7 @@ void ReaderActivity::onSelectBookFile(const std::string& path) {
|
||||
onGoToEpubReader(std::move(epub));
|
||||
} else {
|
||||
exitActivity();
|
||||
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInput, "Failed to load epub",
|
||||
enterNewActivity(new FullScreenMessageActivity(renderer, mappedInput, "Chargement de l'epub échoué",
|
||||
EpdFontFamily::REGULAR, EInkDisplay::HALF_REFRESH));
|
||||
delay(2000);
|
||||
onGoToFileSelection();
|
||||
|
||||
@ -251,7 +251,7 @@ void XtcReaderActivity::renderPage() {
|
||||
pixelCounts[getPixelValue(x, y)]++;
|
||||
}
|
||||
}
|
||||
Serial.printf("[%lu] [XTR] Pixel distribution: White=%lu, DarkGrey=%lu, LightGrey=%lu, Black=%lu\n", millis(),
|
||||
Serial.printf("[%lu] [XTR] Distribution des pixels: Blanc=%lu, GrisFoncé=%lu, GrisPâle=%lu, Noir=%lu\n", millis(),
|
||||
pixelCounts[0], pixelCounts[1], pixelCounts[2], pixelCounts[3]);
|
||||
|
||||
// Pass 1: BW buffer - draw all non-white pixels as black
|
||||
@ -315,7 +315,7 @@ void XtcReaderActivity::renderPage() {
|
||||
|
||||
free(pageBuffer);
|
||||
|
||||
Serial.printf("[%lu] [XTR] Rendered page %lu/%lu (2-bit grayscale)\n", millis(), currentPage + 1,
|
||||
Serial.printf("[%lu] [XTR] Page rendue %lu/%lu en niveaux de gris (2-bits)\n", millis(), currentPage + 1,
|
||||
xtc->getPageCount());
|
||||
return;
|
||||
} else {
|
||||
@ -352,7 +352,7 @@ void XtcReaderActivity::renderPage() {
|
||||
pagesUntilFullRefresh--;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [XTR] Rendered page %lu/%lu (%u-bit)\n", millis(), currentPage + 1, xtc->getPageCount(),
|
||||
Serial.printf("[%lu] [XTR] Page rendue %lu/%lu (%u-bits)\n", millis(), currentPage + 1, xtc->getPageCount(),
|
||||
bitDepth);
|
||||
}
|
||||
|
||||
@ -375,7 +375,7 @@ void XtcReaderActivity::loadProgress() {
|
||||
uint8_t data[4];
|
||||
if (f.read(data, 4) == 4) {
|
||||
currentPage = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||
Serial.printf("[%lu] [XTR] Loaded progress: page %lu\n", millis(), currentPage);
|
||||
Serial.printf("[%lu] [XTR] Progrès chargé: page %lu\n", millis(), currentPage);
|
||||
|
||||
// Validate page number
|
||||
if (currentPage >= xtc->getPageCount()) {
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
namespace {
|
||||
constexpr int MENU_ITEMS = 2;
|
||||
const char* menuNames[MENU_ITEMS] = {"Calibre Web URL", "Connect as Wireless Device"};
|
||||
const char* menuNames[MENU_ITEMS] = {"URL web Calibre", "Connecter en tant qu'un appareil sans fil"};
|
||||
} // namespace
|
||||
|
||||
void CalibreSettingsActivity::taskTrampoline(void* param) {
|
||||
@ -83,7 +83,7 @@ void CalibreSettingsActivity::handleSelection() {
|
||||
// Calibre Web URL
|
||||
exitActivity();
|
||||
enterNewActivity(new KeyboardEntryActivity(
|
||||
renderer, mappedInput, "Calibre Web URL", SETTINGS.opdsServerUrl, 10,
|
||||
renderer, mappedInput, "URL web Calibre", SETTINGS.opdsServerUrl, 10,
|
||||
127, // maxLength
|
||||
false, // not password
|
||||
[this](const std::string& url) {
|
||||
@ -155,14 +155,14 @@ void CalibreSettingsActivity::render() {
|
||||
|
||||
// Draw status for URL setting
|
||||
if (i == 0) {
|
||||
const char* status = (strlen(SETTINGS.opdsServerUrl) > 0) ? "[Set]" : "[Not Set]";
|
||||
const char* status = (strlen(SETTINGS.opdsServerUrl) > 0) ? "[Défini]" : "[Indéfini]";
|
||||
const auto width = renderer.getTextWidth(UI_10_FONT_ID, status);
|
||||
renderer.drawText(UI_10_FONT_ID, pageWidth - 20 - width, settingY, status, !isSelected);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw button hints
|
||||
const auto labels = mappedInput.mapLabels("« Back", "Select", "", "");
|
||||
const auto labels = mappedInput.mapLabels("« Retour", "Select.", "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
|
||||
renderer.displayBuffer();
|
||||
|
||||
@ -17,12 +17,12 @@ void OtaUpdateActivity::onWifiSelectionComplete(const bool success) {
|
||||
exitActivity();
|
||||
|
||||
if (!success) {
|
||||
Serial.printf("[%lu] [OTA] WiFi connection failed, exiting\n", millis());
|
||||
Serial.printf("[%lu] [OTA] Connexion au WiFi a échouée, arrêt en cours\n", millis());
|
||||
goBack();
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [OTA] WiFi connected, checking for update\n", millis());
|
||||
Serial.printf("[%lu] [OTA] WiFi connecté, recherche de mises à jour\n", millis());
|
||||
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
state = CHECKING_FOR_UPDATE;
|
||||
@ -31,7 +31,7 @@ void OtaUpdateActivity::onWifiSelectionComplete(const bool success) {
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
const auto res = updater.checkForUpdate();
|
||||
if (res != OtaUpdater::OK) {
|
||||
Serial.printf("[%lu] [OTA] Update check failed: %d\n", millis(), res);
|
||||
Serial.printf("[%lu] [OTA] Recherce de mises à jour échouée: %d\n", millis(), res);
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
state = FAILED;
|
||||
xSemaphoreGive(renderingMutex);
|
||||
@ -40,7 +40,7 @@ void OtaUpdateActivity::onWifiSelectionComplete(const bool success) {
|
||||
}
|
||||
|
||||
if (!updater.isUpdateNewer()) {
|
||||
Serial.printf("[%lu] [OTA] No new update available\n", millis());
|
||||
Serial.printf("[%lu] [OTA] Aucune nouvelle mise à jour disponible\n", millis());
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
state = NO_UPDATE;
|
||||
xSemaphoreGive(renderingMutex);
|
||||
@ -67,11 +67,11 @@ void OtaUpdateActivity::onEnter() {
|
||||
);
|
||||
|
||||
// Turn on WiFi immediately
|
||||
Serial.printf("[%lu] [OTA] Turning on WiFi...\n", millis());
|
||||
Serial.printf("[%lu] [OTA] Activation du WiFi...\n", millis());
|
||||
WiFi.mode(WIFI_STA);
|
||||
|
||||
// Launch WiFi selection subactivity
|
||||
Serial.printf("[%lu] [OTA] Launching WifiSelectionActivity...\n", millis());
|
||||
Serial.printf("[%lu] [OTA] Lancement de WifiSelectionActivity...\n", millis());
|
||||
enterNewActivity(new WifiSelectionActivity(renderer, mappedInput,
|
||||
[this](const bool connected) { onWifiSelectionComplete(connected); }));
|
||||
}
|
||||
@ -115,7 +115,7 @@ void OtaUpdateActivity::render() {
|
||||
|
||||
float updaterProgress = 0;
|
||||
if (state == UPDATE_IN_PROGRESS) {
|
||||
Serial.printf("[%lu] [OTA] Update progress: %d / %d\n", millis(), updater.processedSize, updater.totalSize);
|
||||
Serial.printf("[%lu] [OTA] Progrès de la mise à jour : %d / %d\n", millis(), updater.processedSize, updater.totalSize);
|
||||
updaterProgress = static_cast<float>(updater.processedSize) / static_cast<float>(updater.totalSize);
|
||||
// Only update every 2% at the most
|
||||
if (static_cast<int>(updaterProgress * 50) == lastUpdaterPercentage / 2) {
|
||||
@ -127,27 +127,27 @@ void OtaUpdateActivity::render() {
|
||||
const auto pageWidth = renderer.getScreenWidth();
|
||||
|
||||
renderer.clearScreen();
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Update", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Mise à jour", true, EpdFontFamily::BOLD);
|
||||
|
||||
if (state == CHECKING_FOR_UPDATE) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Checking for update...", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Recherche de mises à jour...", true, EpdFontFamily::BOLD);
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == WAITING_CONFIRMATION) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 200, "New update available!", true, EpdFontFamily::BOLD);
|
||||
renderer.drawText(UI_10_FONT_ID, 20, 250, "Current Version: " CROSSPOINT_VERSION);
|
||||
renderer.drawText(UI_10_FONT_ID, 20, 270, ("New Version: " + updater.getLatestVersion()).c_str());
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 200, "Une mise à jour est disponible!", true, EpdFontFamily::BOLD);
|
||||
renderer.drawText(UI_10_FONT_ID, 20, 250, "Version actuelle: " CROSSPOINT_VERSION);
|
||||
renderer.drawText(UI_10_FONT_ID, 20, 270, ("Nouvelle version: " + updater.getLatestVersion()).c_str());
|
||||
|
||||
const auto labels = mappedInput.mapLabels("Cancel", "Update", "", "");
|
||||
const auto labels = mappedInput.mapLabels("Annuler", "M-à-j", "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == UPDATE_IN_PROGRESS) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 310, "Updating...", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 310, "Mise à jour...", true, EpdFontFamily::BOLD);
|
||||
renderer.drawRect(20, 350, pageWidth - 40, 50);
|
||||
renderer.fillRect(24, 354, static_cast<int>(updaterProgress * static_cast<float>(pageWidth - 44)), 42);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 420,
|
||||
@ -160,20 +160,20 @@ void OtaUpdateActivity::render() {
|
||||
}
|
||||
|
||||
if (state == NO_UPDATE) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "No update available", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Aucune novelle mise à jour disponible", true, EpdFontFamily::BOLD);
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == FAILED) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Update failed", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Mise à jour échouée", true, EpdFontFamily::BOLD);
|
||||
renderer.displayBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == FINISHED) {
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Update complete", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 350, "Press and hold power button to turn back on");
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Mise à jour terminée", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 350, "Appuyez longuement sur le bouton d'alimentation pour rallumer");
|
||||
renderer.displayBuffer();
|
||||
state = SHUTTING_DOWN;
|
||||
return;
|
||||
@ -188,7 +188,7 @@ void OtaUpdateActivity::loop() {
|
||||
|
||||
if (state == WAITING_CONFIRMATION) {
|
||||
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
|
||||
Serial.printf("[%lu] [OTA] New update available, starting download...\n", millis());
|
||||
Serial.printf("[%lu] [OTA] Nouvelle mise à jour disponible, téléchargement commencé...\n", millis());
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
state = UPDATE_IN_PROGRESS;
|
||||
xSemaphoreGive(renderingMutex);
|
||||
@ -197,7 +197,7 @@ void OtaUpdateActivity::loop() {
|
||||
const auto res = updater.installUpdate([this](const size_t, const size_t) { updateRequired = true; });
|
||||
|
||||
if (res != OtaUpdater::OK) {
|
||||
Serial.printf("[%lu] [OTA] Update failed: %d\n", millis(), res);
|
||||
Serial.printf("[%lu] [OTA] Mise à jour échouée: %d\n", millis(), res);
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
state = FAILED;
|
||||
xSemaphoreGive(renderingMutex);
|
||||
|
||||
@ -16,31 +16,31 @@ namespace {
|
||||
constexpr int settingsCount = 18;
|
||||
const SettingInfo settingsList[settingsCount] = {
|
||||
// Should match with SLEEP_SCREEN_MODE
|
||||
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
|
||||
SettingInfo::Enum("Sleep Screen Cover Mode", &CrossPointSettings::sleepScreenCoverMode, {"Fit", "Crop"}),
|
||||
SettingInfo::Enum("Status Bar", &CrossPointSettings::statusBar, {"None", "No Progress", "Full"}),
|
||||
SettingInfo::Toggle("Extra Paragraph Spacing", &CrossPointSettings::extraParagraphSpacing),
|
||||
SettingInfo::Toggle("Text Anti-Aliasing", &CrossPointSettings::textAntiAliasing),
|
||||
SettingInfo::Toggle("Short Power Button Click", &CrossPointSettings::shortPwrBtn),
|
||||
SettingInfo::Enum("Reading Orientation", &CrossPointSettings::orientation,
|
||||
{"Portrait", "Landscape CW", "Inverted", "Landscape CCW"}),
|
||||
SettingInfo::Enum("Front Button Layout", &CrossPointSettings::frontButtonLayout,
|
||||
{"Bck, Cnfrm, Lft, Rght", "Lft, Rght, Bck, Cnfrm", "Lft, Bck, Cnfrm, Rght"}),
|
||||
SettingInfo::Enum("Side Button Layout (reader)", &CrossPointSettings::sideButtonLayout,
|
||||
{"Prev, Next", "Next, Prev"}),
|
||||
SettingInfo::Enum("Reader Font Family", &CrossPointSettings::fontFamily,
|
||||
SettingInfo::Enum("Écran de veille", &CrossPointSettings::sleepScreen, {"Sombre", "Clair", "Personnalisé", "Couverture", "Aucun"}),
|
||||
SettingInfo::Enum("Mode de couverture de veille", &CrossPointSettings::sleepScreenCoverMode, {"Étirée", "Recadrée"}),
|
||||
SettingInfo::Enum("Barre d'état", &CrossPointSettings::statusBar, {"Aucune", "Sans progrès", "Pleine"}),
|
||||
SettingInfo::Toggle("Espace supplé. entre paragraphes", &CrossPointSettings::extraParagraphSpacing),
|
||||
SettingInfo::Toggle("Anticrénelage du texte", &CrossPointSettings::textAntiAliasing),
|
||||
SettingInfo::Toggle("Clic court du bouton alim.", &CrossPointSettings::shortPwrBtn),
|
||||
SettingInfo::Enum("Orientation de lecture", &CrossPointSettings::orientation,
|
||||
{"Portrait", "Paysage à droite", "Inversée", "Paysage à gauche"}),
|
||||
SettingInfo::Enum("Disposition des boutons au front", &CrossPointSettings::frontButtonLayout,
|
||||
{"Rtr, Cnfrmr, Gche, Drte", "Gche, Drte, Rtr, Cnfrmr", "Gche, Rtr, Cnfrmr, Drte"}),
|
||||
SettingInfo::Enum("Disposition des boutons à droite (lis.)", &CrossPointSettings::sideButtonLayout,
|
||||
{"Précédent, Prochaine", "Prochaine, Précédent"}),
|
||||
SettingInfo::Enum("Police", &CrossPointSettings::fontFamily,
|
||||
{"Bookerly", "Noto Sans", "Open Dyslexic"}),
|
||||
SettingInfo::Enum("Reader Font Size", &CrossPointSettings::fontSize, {"Small", "Medium", "Large", "X Large"}),
|
||||
SettingInfo::Enum("Reader Line Spacing", &CrossPointSettings::lineSpacing, {"Tight", "Normal", "Wide"}),
|
||||
SettingInfo::Value("Reader Screen Margin", &CrossPointSettings::screenMargin, {5, 40, 5}),
|
||||
SettingInfo::Enum("Reader Paragraph Alignment", &CrossPointSettings::paragraphAlignment,
|
||||
{"Justify", "Left", "Center", "Right"}),
|
||||
SettingInfo::Enum("Time to Sleep", &CrossPointSettings::sleepTimeout,
|
||||
SettingInfo::Enum("Taille de police", &CrossPointSettings::fontSize, {"Petit", "Medium", "Large", "Très Large"}),
|
||||
SettingInfo::Enum("Espacement des lignes", &CrossPointSettings::lineSpacing, {"Fin", "Normal", "Large"}),
|
||||
SettingInfo::Value("Marge d'écran", &CrossPointSettings::screenMargin, {5, 40, 5}),
|
||||
SettingInfo::Enum("Alignement des lignes", &CrossPointSettings::paragraphAlignment,
|
||||
{"Justifié", "Gauche", "Centré", "Droite"}),
|
||||
SettingInfo::Enum("Temps de veille", &CrossPointSettings::sleepTimeout,
|
||||
{"1 min", "5 min", "10 min", "15 min", "30 min"}),
|
||||
SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency,
|
||||
SettingInfo::Enum("Fréquence de rafraîche.", &CrossPointSettings::refreshFrequency,
|
||||
{"1 page", "5 pages", "10 pages", "15 pages", "30 pages"}),
|
||||
SettingInfo::Action("Calibre Settings"),
|
||||
SettingInfo::Action("Check for updates")};
|
||||
SettingInfo::Action("Paramètres Calibre"),
|
||||
SettingInfo::Action("Vérifier les mises à jour")};
|
||||
} // namespace
|
||||
|
||||
void SettingsActivity::taskTrampoline(void* param) {
|
||||
@ -137,7 +137,7 @@ void SettingsActivity::toggleCurrentSetting() {
|
||||
SETTINGS.*(setting.valuePtr) = currentValue + setting.valueRange.step;
|
||||
}
|
||||
} else if (setting.type == SettingType::ACTION) {
|
||||
if (strcmp(setting.name, "Calibre Settings") == 0) {
|
||||
if (strcmp(setting.name, "Paramètres Calibre") == 0) {
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
exitActivity();
|
||||
enterNewActivity(new CalibreSettingsActivity(renderer, mappedInput, [this] {
|
||||
@ -145,7 +145,7 @@ void SettingsActivity::toggleCurrentSetting() {
|
||||
updateRequired = true;
|
||||
}));
|
||||
xSemaphoreGive(renderingMutex);
|
||||
} else if (strcmp(setting.name, "Check for updates") == 0) {
|
||||
} else if (strcmp(setting.name, "Verifier les mises à jour") == 0) {
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
exitActivity();
|
||||
enterNewActivity(new OtaUpdateActivity(renderer, mappedInput, [this] {
|
||||
@ -182,7 +182,7 @@ void SettingsActivity::render() const {
|
||||
const auto pageHeight = renderer.getScreenHeight();
|
||||
|
||||
// Draw header
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Settings", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Paramètres", true, EpdFontFamily::BOLD);
|
||||
|
||||
// Draw selection
|
||||
renderer.fillRect(0, 60 + selectedSettingIndex * 30 - 2, pageWidth - 1, 30);
|
||||
@ -198,7 +198,7 @@ void SettingsActivity::render() const {
|
||||
std::string valueText = "";
|
||||
if (settingsList[i].type == SettingType::TOGGLE && settingsList[i].valuePtr != nullptr) {
|
||||
const bool value = SETTINGS.*(settingsList[i].valuePtr);
|
||||
valueText = value ? "ON" : "OFF";
|
||||
valueText = value ? "OUI" : "NON";
|
||||
} else if (settingsList[i].type == SettingType::ENUM && settingsList[i].valuePtr != nullptr) {
|
||||
const uint8_t value = SETTINGS.*(settingsList[i].valuePtr);
|
||||
valueText = settingsList[i].enumValues[value];
|
||||
@ -214,7 +214,7 @@ void SettingsActivity::render() const {
|
||||
pageHeight - 60, CROSSPOINT_VERSION);
|
||||
|
||||
// Draw help text
|
||||
const auto labels = mappedInput.mapLabels("« Save", "Toggle", "", "");
|
||||
const auto labels = mappedInput.mapLabels("« Enreg.", "Basculer", "", "");
|
||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
|
||||
// Always use standard refresh for settings screen
|
||||
|
||||
Loading…
Reference in New Issue
Block a user