Skip to content

Commit 1959768

Browse files
authored
Merge pull request #48 from jblanked/dev
FlipSocial - v2.0.9 - Added support for loading a custom dictionary for the keyboard auto-complete functionality (stored in "apps_data/flip_social/dictionary.txt" with each word/phrase separated by a newline). - Updated the Explore view to allow users to click on a user to either add them as a friend or send them a message. - Updated the Profile view to allow users to click on their friend count to view a list of their friends and then click on a friend to optionally remove them. - Updated the Profile view to allow users to click on their bio to edit it.
2 parents 8d8c001 + 90c492b commit 1959768

File tree

14 files changed

+967
-40
lines changed

14 files changed

+967
-40
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ The highlight of this app is customizable pre-saves, which, as explained below,
1919
- Feed (with comments, flipping, and posting)
2020
- Profile
2121
- Customizable Pre-Saves
22+
- AutoComplete keyboard
2223
- Explore
2324
- Friends
2425
- Direct Messaging

app.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include "about/about.hpp"
88

99
#define TAG "FlipSocial"
10-
#define VERSION "2.0.8"
10+
#define VERSION "2.0.9"
1111
#define VERSION_TAG TAG " " VERSION
1212
#define APP_ID "flip_social"
1313

application.fam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ App(
99
fap_icon_assets="assets",
1010
fap_author="JBlanked",
1111
fap_weburl="https://github.com/jblanked/FlipSocial",
12-
fap_version="2.0.8",
12+
fap_version="2.0.9",
1313
fap_description="Social media platform for the Flipper Zero.",
1414
)

assets/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 2.0.9
2+
- Added support for loading a custom dictionary for the keyboard auto-complete functionality (stored in "apps_data/flip_social/dictionary.txt" with each word/phrase separated by a newline).
3+
- Updated the Explore view to allow users to click on a user to either add them as a friend or send them a message.
4+
- Updated the Profile view to allow users to click on their friend count to view a list of their friends and then click on a friend to optionally remove them.
5+
- Updated the Profile view to allow users to click on their bio to edit it.
6+
17
## 2.0.8
28
- Updated auto-complete functionality to accept and return multi-word suggestions.
39
- Moved the keyboard class to its own folder for better organization.

assets/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ The highlight of this app is customizable pre-saves, which, as explained below,
1919
- Feed (with comments, flipping, and posting)
2020
- Profile
2121
- Customizable Pre-Saves
22+
- AutoComplete keyboard
2223
- Explore
2324
- Friends
2425
- Direct Messaging

assets/flip-social-main-menu.png

-15 Bytes
Loading

auto_complete/auto_complete.c

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "auto_complete.h"
2+
#include MEMORY_INCLUDE
23

34
// Get index for character (a-z maps to 0-25, space maps to 26)
45
static int char_to_index(char c)
@@ -26,13 +27,13 @@ static void collect_words(TrieNode *node, AutoComplete *context)
2627
const size_t len = strlen(node->word);
2728

2829
// Reallocate suggestions array to fit one more suggestion
29-
char **new_suggestions = (char **)realloc(context->suggestions,
30-
(context->suggestion_count + 1) * sizeof(char *));
30+
char **new_suggestions = (char **)MEMORY_REALLOC(context->suggestions,
31+
(context->suggestion_count + 1) * sizeof(char *));
3132
if (!new_suggestions)
3233
return;
3334

3435
context->suggestions = new_suggestions;
35-
context->suggestions[context->suggestion_count] = (char *)malloc(len + 1);
36+
context->suggestions[context->suggestion_count] = (char *)MEMORY_ALLOC(len + 1);
3637
if (context->suggestions[context->suggestion_count])
3738
{
3839
snprintf(context->suggestions[context->suggestion_count], len + 1, "%s", node->word);
@@ -56,7 +57,7 @@ static void collect_words(TrieNode *node, AutoComplete *context)
5657
// Create new trie node
5758
static TrieNode *create_node(void)
5859
{
59-
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode));
60+
TrieNode *node = (TrieNode *)MEMORY_ALLOC(sizeof(TrieNode));
6061
if (!node)
6162
return NULL;
6263

@@ -84,15 +85,60 @@ static void free_trie(TrieNode *node)
8485

8586
if (node->word)
8687
{
87-
free(node->word);
88+
MEMORY_FREE(node->word);
8889
node->word = NULL;
8990
}
9091

91-
free(node);
92+
MEMORY_FREE(node);
9293
node = NULL;
9394
}
9495
}
9596

97+
#if defined(STORAGE_INCLUDE) && defined(STORAGE_READ)
98+
bool auto_complete_add_dictionary(AutoComplete *context, const char *filename)
99+
{
100+
if (!context || !filename)
101+
return false;
102+
103+
char *buffer = (char *)MEMORY_ALLOC(STORAGE_MAX_READ_SIZE);
104+
if (!buffer)
105+
return false;
106+
107+
size_t bytes_read = STORAGE_READ(filename, buffer, STORAGE_MAX_READ_SIZE);
108+
if (bytes_read == 0)
109+
{
110+
MEMORY_FREE(buffer);
111+
return false;
112+
}
113+
114+
char *start = buffer;
115+
char *end = buffer;
116+
int count = 0;
117+
118+
while (*end && count < MAX_SUGGESTIONS)
119+
{
120+
if (*end == '\n' || *end == '\r')
121+
{
122+
*end = '\0'; // Null-terminate the word
123+
if (strlen(start) > 0)
124+
{
125+
auto_complete_add_word(context, start);
126+
count++;
127+
}
128+
end++;
129+
start = end;
130+
}
131+
else
132+
{
133+
end++;
134+
}
135+
}
136+
137+
MEMORY_FREE(buffer);
138+
return true;
139+
}
140+
#endif
141+
96142
// Add word to dictionary
97143
bool auto_complete_add_word(AutoComplete *context, const char *word)
98144
{
@@ -124,7 +170,7 @@ bool auto_complete_add_word(AutoComplete *context, const char *word)
124170
current->is_end_of_word = true;
125171

126172
// Store complete word at end node
127-
current->word = (char *)malloc(len + 1);
173+
current->word = (char *)MEMORY_ALLOC(len + 1);
128174
if (current->word)
129175
{
130176
snprintf(current->word, len + 1, "%s", word);
@@ -149,11 +195,11 @@ void auto_complete_free(AutoComplete *context)
149195
{
150196
if (context->suggestions[i])
151197
{
152-
free(context->suggestions[i]);
198+
MEMORY_FREE(context->suggestions[i]);
153199
context->suggestions[i] = NULL;
154200
}
155201
}
156-
free(context->suggestions);
202+
MEMORY_FREE(context->suggestions);
157203
context->suggestions = NULL;
158204
}
159205
context->suggestion_count = 0;
@@ -182,11 +228,11 @@ void auto_complete_remove_suggestions(AutoComplete *context)
182228
{
183229
if (context->suggestions[i])
184230
{
185-
free(context->suggestions[i]);
231+
MEMORY_FREE(context->suggestions[i]);
186232
context->suggestions[i] = NULL;
187233
}
188234
}
189-
free(context->suggestions);
235+
MEMORY_FREE(context->suggestions);
190236
context->suggestions = NULL;
191237
context->suggestion_count = 0;
192238
}

auto_complete/auto_complete.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
#include <stddef.h>
44
#include <string.h>
5-
#include <stdlib.h>
65
#include <stdio.h>
76
#include <stdbool.h>
87
#include <ctype.h>
98
#include <stdint.h>
109

10+
#include "auto_complete_config.h"
11+
1112
#define MAX_WORD_LENGTH 32
1213
#define MAX_SUGGESTIONS 10
1314
#define ALPHABET_SIZE 27 // a-z + space
@@ -31,6 +32,11 @@ extern "C"
3132
uint8_t suggestion_count;
3233
} AutoComplete;
3334

35+
#if defined(STORAGE_INCLUDE) && defined(STORAGE_READ)
36+
#include STORAGE_INCLUDE
37+
bool auto_complete_add_dictionary(AutoComplete *context, const char *filename);
38+
#endif
39+
3440
bool auto_complete_add_word(AutoComplete *context, const char *word);
3541
void auto_complete_free(AutoComplete *context);
3642
bool auto_complete_init(AutoComplete *context);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
// memory info
4+
#define MEMORY_INCLUDE "stdlib.h"
5+
#define MEMORY_ALLOC malloc
6+
#define MEMORY_FREE free
7+
#define MEMORY_REALLOC realloc
8+
9+
// storage info
10+
#define STORAGE_INCLUDE "auto_complete/storage.h"
11+
#define STORAGE_READ storage_read
12+
#define STORAGE_MAX_READ_SIZE 4096

auto_complete/storage.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#pragma once
2+
#include <furi.h>
3+
#include <storage/storage.h>
4+
5+
#ifdef __cplusplus
6+
extern "C"
7+
{
8+
#endif
9+
10+
static inline size_t storage_read(const char *file_path, char *buffer, size_t buffer_size)
11+
{
12+
Storage *storage = (Storage *)furi_record_open(RECORD_STORAGE);
13+
File *file = storage_file_alloc(storage);
14+
15+
// Open the file for reading
16+
if (!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING))
17+
{
18+
storage_file_free(file);
19+
furi_record_close(RECORD_STORAGE);
20+
return 0;
21+
}
22+
23+
// Read data into the buffer
24+
size_t read_count = storage_file_read(file, buffer, buffer_size);
25+
if (storage_file_get_error(file) != FSE_OK)
26+
{
27+
FURI_LOG_E("storage", "Error reading from file.");
28+
storage_file_close(file);
29+
storage_file_free(file);
30+
furi_record_close(RECORD_STORAGE);
31+
return 0;
32+
}
33+
34+
// Ensure null-termination
35+
if (read_count > 0 && read_count < buffer_size)
36+
{
37+
buffer[read_count] = '\0';
38+
}
39+
else if (buffer_size > 0)
40+
{
41+
buffer[buffer_size - 1] = '\0';
42+
}
43+
44+
storage_file_close(file);
45+
storage_file_free(file);
46+
furi_record_close(RECORD_STORAGE);
47+
48+
return read_count;
49+
}
50+
51+
#ifdef __cplusplus
52+
}
53+
#endif

0 commit comments

Comments
 (0)