Compare commits

...

4 Commits

Author SHA1 Message Date
James Whyte
e37ca90c6b
Merge b5922b91b7 into f67c544e16 2026-02-02 11:24:32 +00:00
Aaron Cunliffe
f67c544e16
fix: webserver folder creation regex change (#653)
Some checks failed
CI / build (push) Has been cancelled
## Summary

Resolves #562 

Implements regex change to support valid characters discussed by
@daveallie in issue
[here](https://github.com/crosspoint-reader/crosspoint-reader/issues/562#issuecomment-3830809156).

Also rejects `.` and `..` as folder names which are invalid in FAT32 and
exFAT filesystems

## Additional Context
- Unsure on the wording for the alert, it feels overly explicit, but
that might be a good thing. Happy to change.

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**< PARTIALLY >**_
2026-02-02 21:27:02 +11:00
James Whyte
b5922b91b7 feat: add shift lock to KeyboardEntryActivity 2026-01-23 17:19:38 +00:00
James Whyte
93ea23168b fix: disable shift after any typed character 2026-01-23 16:29:08 +00:00
4 changed files with 17 additions and 13 deletions

View File

@ -153,7 +153,7 @@ Click **File Manager** to access file management features.
1. Click the **+ Add** button in the top-right corner
2. Select **New Folder** from the dropdown menu
3. Enter a folder name (letters, numbers, underscores, and hyphens only)
3. Enter a folder name (must not contain characters \" * : < > ? / \\ | and must not be . or ..)
4. Click **Create Folder**
This is useful for organizing your ebooks by genre, author, or series.

View File

@ -13,6 +13,9 @@ const char* const KeyboardEntryActivity::keyboard[NUM_ROWS] = {
const char* const KeyboardEntryActivity::keyboardShift[NUM_ROWS] = {"~!@#$%^&*()_+", "QWERTYUIOP{}|", "ASDFGHJKL:\"",
"ZXCVBNM<>?", "SPECIAL ROW"};
// Shift state strings
const char* const KeyboardEntryActivity::shiftString[3] = {"shift", "SHIFT", "LOCK"};
void KeyboardEntryActivity::taskTrampoline(void* param) {
auto* self = static_cast<KeyboardEntryActivity*>(param);
self->displayTaskLoop();
@ -80,7 +83,7 @@ int KeyboardEntryActivity::getRowLength(const int row) const {
}
char KeyboardEntryActivity::getSelectedChar() const {
const char* const* layout = shiftActive ? keyboardShift : keyboard;
const char* const* layout = shiftState ? keyboardShift : keyboard;
if (selectedRow < 0 || selectedRow >= NUM_ROWS) return '\0';
if (selectedCol < 0 || selectedCol >= getRowLength(selectedRow)) return '\0';
@ -92,8 +95,8 @@ void KeyboardEntryActivity::handleKeyPress() {
// Handle special row (bottom row with shift, space, backspace, done)
if (selectedRow == SPECIAL_ROW) {
if (selectedCol >= SHIFT_COL && selectedCol < SPACE_COL) {
// Shift toggle
shiftActive = !shiftActive;
// Shift toggle (0 = lower case, 1 = upper case, 2 = shift lock)
shiftState = (shiftState + 1) % 3;
return;
}
@ -130,9 +133,9 @@ void KeyboardEntryActivity::handleKeyPress() {
if (maxLength == 0 || text.length() < maxLength) {
text += c;
// Auto-disable shift after typing a letter
if (shiftActive && ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) {
shiftActive = false;
// Auto-disable shift after typing a character in non-lock mode
if (shiftState == 1) {
shiftState = 0;
}
}
}
@ -297,7 +300,7 @@ void KeyboardEntryActivity::render() const {
constexpr int keyHeight = 18;
constexpr int keySpacing = 3;
const char* const* layout = shiftActive ? keyboardShift : keyboard;
const char* const* layout = shiftState ? keyboardShift : keyboard;
// Calculate left margin to center the longest row (13 keys)
constexpr int maxRowWidth = KEYS_PER_ROW * (keyWidth + keySpacing);
@ -318,7 +321,7 @@ void KeyboardEntryActivity::render() const {
// SHIFT key (logical col 0, spans 2 key widths)
const bool shiftSelected = (selectedRow == 4 && selectedCol >= SHIFT_COL && selectedCol < SPACE_COL);
renderItemWithSelector(currentX + 2, rowY, shiftActive ? "SHIFT" : "shift", shiftSelected);
renderItemWithSelector(currentX + 2, rowY, shiftString[shiftState], shiftSelected);
currentX += 2 * (keyWidth + keySpacing);
// Space bar (logical cols 2-6, spans 5 key widths)

View File

@ -70,7 +70,7 @@ class KeyboardEntryActivity : public Activity {
// Keyboard state
int selectedRow = 0;
int selectedCol = 0;
bool shiftActive = false;
int shiftState = 0; // 0 = lower case, 1 = upper case, 2 = shift lock)
// Callbacks
OnCompleteCallback onComplete;
@ -81,6 +81,7 @@ class KeyboardEntryActivity : public Activity {
static constexpr int KEYS_PER_ROW = 13; // Max keys per row (rows 0 and 1 have 13 keys)
static const char* const keyboard[NUM_ROWS];
static const char* const keyboardShift[NUM_ROWS];
static const char* const shiftString[3];
// Special key positions (bottom row)
static constexpr int SPECIAL_ROW = 4;

View File

@ -1146,10 +1146,10 @@ function retryAllFailedUploads() {
return;
}
// Validate folder name (no special characters except underscore and hyphen)
const validName = /^[a-zA-Z0-9_\-]+$/.test(folderName);
// Validate folder name
const validName = /^(?!\.{1,2}$)[^"*:<>?\/\\|]+$/.test(folderName);
if (!validName) {
alert('Folder name can only contain letters, numbers, underscores, and hyphens.');
alert('Folder name cannot contain \" * : < > ? / \\ | and must not be . or ..');
return;
}