flip_social_draw.h 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. #ifndef FLIP_SOCIAL_DRAW_H
  2. #define FLIP_SOCIAL_DRAW_H
  3. bool flip_social_sent_login_request = false;
  4. bool flip_social_sent_register_request = false;
  5. bool flip_social_login_success = false;
  6. bool flip_social_register_success = false;
  7. bool flip_social_dialog_shown = false;
  8. bool flip_social_dialog_stop = false;
  9. char* last_explore_response = "";
  10. static bool flip_social_update_friends();
  11. bool flip_social_board_is_active(Canvas* canvas) {
  12. if(fhttp.state == INACTIVE) {
  13. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  14. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  15. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  16. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  17. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  18. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  19. return false;
  20. }
  21. return true;
  22. }
  23. void flip_social_handle_error(Canvas* canvas) {
  24. if(fhttp.received_data != NULL) {
  25. if(strstr(fhttp.received_data, "[ERROR] Not connected to Wifi. Failed to reconnect.") !=
  26. NULL) {
  27. canvas_clear(canvas);
  28. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  29. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  30. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  31. } else if(strstr(fhttp.received_data, "[ERROR] Failed to connect to Wifi.") != NULL) {
  32. canvas_clear(canvas);
  33. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  34. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  35. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  36. } else {
  37. canvas_draw_str(canvas, 0, 42, "Failed...");
  38. canvas_draw_str(canvas, 0, 52, "Update your credentials.");
  39. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  40. }
  41. } else {
  42. canvas_draw_str(canvas, 0, 42, "Failed...");
  43. canvas_draw_str(canvas, 0, 52, "Update your credentials.");
  44. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  45. }
  46. }
  47. static void on_input(const void* event, void* ctx) {
  48. UNUSED(ctx);
  49. InputKey key = ((InputEvent*)event)->key;
  50. InputType type = ((InputEvent*)event)->type;
  51. if(type != InputTypeRelease) {
  52. return;
  53. }
  54. switch(key) {
  55. case InputKeyOk:
  56. action = ActionFlip;
  57. break;
  58. case InputKeyBack:
  59. action = ActionBack;
  60. break;
  61. case InputKeyRight:
  62. action = ActionNext;
  63. break;
  64. case InputKeyLeft:
  65. action = ActionPrev;
  66. break;
  67. case InputKeyUp:
  68. action = ActionPrev;
  69. break;
  70. case InputKeyDown:
  71. action = ActionNext;
  72. break;
  73. default:
  74. action = ActionNone;
  75. break;
  76. }
  77. }
  78. // Function to draw the message on the canvas with word wrapping
  79. void draw_user_message(Canvas* canvas, const char* user_message, int x, int y) {
  80. if(user_message == NULL) {
  81. FURI_LOG_E(TAG, "User message is NULL.");
  82. return;
  83. }
  84. size_t msg_length = strlen(user_message);
  85. size_t start = 0;
  86. int line_num = 0;
  87. char line[MAX_LINE_LENGTH + 1]; // Buffer for the current line (+1 for null terminator)
  88. while(start < msg_length && line_num < 4) {
  89. size_t remaining = msg_length - start;
  90. size_t len = (remaining > MAX_LINE_LENGTH) ? MAX_LINE_LENGTH : remaining;
  91. if(remaining > MAX_LINE_LENGTH) {
  92. // Find the last space within the first 'len' characters
  93. size_t last_space = len;
  94. while(last_space > 0 && user_message[start + last_space - 1] != ' ') {
  95. last_space--;
  96. }
  97. if(last_space > 0) {
  98. len = last_space; // Adjust len to the position of the last space
  99. }
  100. }
  101. // Copy the substring to 'line' and null-terminate it
  102. memcpy(line, user_message + start, len);
  103. line[len] = '\0'; // Ensure the string is null-terminated
  104. // Draw the string on the canvas
  105. // Adjust the y-coordinate based on the line number
  106. canvas_draw_str_aligned(canvas, x, y + line_num * 10, AlignLeft, AlignTop, line);
  107. // Update the start position for the next line
  108. start += len;
  109. // Skip any spaces to avoid leading spaces on the next line
  110. while(start < msg_length && user_message[start] == ' ') {
  111. start++;
  112. }
  113. // Increment the line number
  114. line_num++;
  115. }
  116. }
  117. static void flip_social_callback_draw_compose(Canvas* canvas, void* model) {
  118. UNUSED(model);
  119. if(!canvas) {
  120. FURI_LOG_E(TAG, "Canvas is NULL");
  121. return;
  122. }
  123. if(!app_instance) {
  124. FURI_LOG_E(TAG, "FlipSocialApp is NULL");
  125. return;
  126. }
  127. char* message = app_instance->pre_saved_messages.messages[flip_social_feed->index];
  128. if(!flip_social_dialog_shown) {
  129. flip_social_dialog_shown = true;
  130. app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
  131. app_instance->input_event =
  132. furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
  133. }
  134. draw_user_message(canvas, message, 0, 2);
  135. canvas_draw_icon(canvas, 0, 53, &I_ButtonLeft_4x7);
  136. canvas_draw_str_aligned(canvas, 7, 54, AlignLeft, AlignTop, "Delete");
  137. canvas_draw_icon(canvas, 52, 53, &I_ButtonBACK_10x8);
  138. canvas_draw_str_aligned(canvas, 64, 54, AlignLeft, AlignTop, "Back");
  139. canvas_draw_icon(canvas, 100, 53, &I_ButtonRight_4x7);
  140. canvas_draw_str_aligned(canvas, 107, 54, AlignLeft, AlignTop, "Post");
  141. // handle action
  142. switch(action) {
  143. case ActionNone:
  144. break;
  145. case ActionBack:
  146. flip_social_dialog_stop = true;
  147. break;
  148. case ActionNext:
  149. // send message
  150. if(message && app_instance->login_username_logged_in) {
  151. // Send the message
  152. char command[128];
  153. snprintf(
  154. command,
  155. sizeof(command),
  156. "{\"username\":\"%s\",\"content\":\"%s\"}",
  157. app_instance->login_username_logged_in,
  158. message);
  159. bool success = flipper_http_post_request_with_headers(
  160. "https://www.flipsocial.net/api/feed/post/",
  161. "{\"Content-Type\":\"application/json\"}",
  162. command);
  163. if(!success) {
  164. FURI_LOG_E(TAG, "Failed to send HTTP request for feed");
  165. furi_check(success); // Log the error with furi_check
  166. return; // Exit early to avoid further errors
  167. }
  168. fhttp.state = RECEIVING;
  169. furi_timer_start(fhttp.get_timeout_timer, TIMEOUT_DURATION_TICKS);
  170. } else {
  171. FURI_LOG_E(TAG, "Message or username is NULL");
  172. furi_check(false); // Log as an error and return
  173. return;
  174. }
  175. int i = 0;
  176. while(fhttp.state == RECEIVING && furi_timer_is_running(fhttp.get_timeout_timer) > 0) {
  177. // Wait for the feed to be received
  178. furi_delay_ms(100);
  179. char dots_str[64] = "Receiving";
  180. // Append dots to the string based on the value of i
  181. int dot_count = i % 4;
  182. int len = strlen(dots_str);
  183. snprintf(dots_str + len, sizeof(dots_str) - len, "%.*s", dot_count, "....");
  184. // Draw the resulting string on the canvas
  185. canvas_draw_str(canvas, 0, 30, dots_str);
  186. i++;
  187. }
  188. flip_social_dialog_stop = true;
  189. furi_timer_stop(fhttp.get_timeout_timer);
  190. break;
  191. case ActionPrev:
  192. // delete message
  193. app_instance->pre_saved_messages.messages[flip_social_feed->index] = NULL;
  194. for(uint32_t i = flip_social_feed->index; i < app_instance->pre_saved_messages.count - 1;
  195. i++) {
  196. app_instance->pre_saved_messages.messages[i] =
  197. app_instance->pre_saved_messages.messages[i + 1];
  198. }
  199. app_instance->pre_saved_messages.count--;
  200. // add the item to the submenu
  201. submenu_reset(app_instance->submenu_compose);
  202. submenu_add_item(
  203. app_instance->submenu_compose,
  204. "Add Pre-Save",
  205. FlipSocialSubmenuComposeIndexAddPreSave,
  206. flip_social_callback_submenu_choices,
  207. app_instance);
  208. for(uint32_t i = 0; i < app_instance->pre_saved_messages.count; i++) {
  209. submenu_add_item(
  210. app_instance->submenu_compose,
  211. app_instance->pre_saved_messages.messages[i],
  212. FlipSocialSubemnuComposeIndexStartIndex + i,
  213. flip_social_callback_submenu_choices,
  214. app_instance);
  215. }
  216. // save playlist
  217. save_playlist(&app_instance->pre_saved_messages);
  218. flip_social_dialog_stop = true;
  219. break;
  220. default:
  221. action = ActionNone;
  222. break;
  223. }
  224. if(flip_social_dialog_stop) {
  225. furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
  226. flip_social_dialog_shown = false;
  227. flip_social_dialog_stop = false;
  228. if(action == ActionNext) {
  229. action = ActionNone;
  230. view_dispatcher_switch_to_view(
  231. app_instance->view_dispatcher, FlipSocialViewLoggedInFeed);
  232. } else if(action == ActionBack) {
  233. action = ActionNone;
  234. view_dispatcher_switch_to_view(
  235. app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
  236. } else {
  237. action = ActionNone;
  238. view_dispatcher_switch_to_view(
  239. app_instance->view_dispatcher, FlipSocialViewLoggedInCompose);
  240. }
  241. }
  242. }
  243. // function to draw the dialog canvas
  244. static void flip_social_canvas_draw_message(
  245. Canvas* canvas,
  246. char* user_username,
  247. char* user_message,
  248. bool is_flipped,
  249. bool show_prev,
  250. bool show_next,
  251. int flip_count) {
  252. canvas_set_color(canvas, ColorBlack);
  253. canvas_set_font(canvas, FontPrimary);
  254. canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, user_username);
  255. canvas_set_font(canvas, FontSecondary);
  256. char flip_count_str[12];
  257. if(flip_count == 1) {
  258. snprintf(flip_count_str, sizeof(flip_count_str), "%d Flip", flip_count);
  259. canvas_draw_str_aligned(canvas, 106, 54, AlignLeft, AlignTop, flip_count_str);
  260. } else {
  261. snprintf(flip_count_str, sizeof(flip_count_str), "%d Flips", flip_count);
  262. if(flip_count < 10) {
  263. canvas_draw_str_aligned(canvas, 100, 54, AlignLeft, AlignTop, flip_count_str);
  264. } else if(flip_count < 100) {
  265. canvas_draw_str_aligned(canvas, 94, 54, AlignLeft, AlignTop, flip_count_str);
  266. } else {
  267. canvas_draw_str_aligned(canvas, 88, 54, AlignLeft, AlignTop, flip_count_str);
  268. }
  269. }
  270. draw_user_message(canvas, user_message, 0, 12);
  271. // combine and shift icons/labels around if not show_prev or show_next
  272. if(show_prev && show_next && !is_flipped) {
  273. canvas_draw_icon(canvas, 0, 54, &I_ButtonLeft_4x7);
  274. canvas_draw_str_aligned(canvas, 6, 54, AlignLeft, AlignTop, "Prev");
  275. canvas_draw_icon(canvas, 30, 54, &I_ButtonRight_4x7);
  276. canvas_draw_str_aligned(canvas, 36, 54, AlignLeft, AlignTop, "Next");
  277. canvas_draw_icon(canvas, 58, 54, &I_ButtonOK_7x7);
  278. canvas_draw_str_aligned(canvas, 67, 54, AlignLeft, AlignTop, "Flip");
  279. } else if(show_prev && !show_next && !is_flipped) {
  280. canvas_draw_icon(canvas, 0, 54, &I_ButtonLeft_4x7);
  281. canvas_draw_str_aligned(canvas, 6, 54, AlignLeft, AlignTop, "Prev");
  282. canvas_draw_icon(canvas, 28, 54, &I_ButtonOK_7x7);
  283. canvas_draw_str_aligned(canvas, 37, 54, AlignLeft, AlignTop, "Flip");
  284. } else if(!show_prev && show_next && !is_flipped) {
  285. canvas_draw_icon(canvas, 0, 54, &I_ButtonRight_4x7);
  286. canvas_draw_str_aligned(canvas, 6, 54, AlignLeft, AlignTop, "Next");
  287. canvas_draw_icon(canvas, 28, 54, &I_ButtonOK_7x7);
  288. canvas_draw_str_aligned(canvas, 37, 54, AlignLeft, AlignTop, "Flip");
  289. } else if(show_prev && show_next && is_flipped) {
  290. canvas_draw_icon(canvas, 0, 54, &I_ButtonLeft_4x7);
  291. canvas_draw_str_aligned(canvas, 6, 54, AlignLeft, AlignTop, "Prev");
  292. canvas_draw_icon(canvas, 28, 54, &I_ButtonRight_4x7);
  293. canvas_draw_str_aligned(canvas, 34, 54, AlignLeft, AlignTop, "Next");
  294. canvas_draw_icon(canvas, 54, 54, &I_ButtonOK_7x7);
  295. canvas_draw_str_aligned(canvas, 63, 54, AlignLeft, AlignTop, "UnFlip");
  296. } else if(show_prev && !show_next && is_flipped) {
  297. canvas_draw_icon(canvas, 0, 54, &I_ButtonLeft_4x7);
  298. canvas_draw_str_aligned(canvas, 6, 54, AlignLeft, AlignTop, "Prev");
  299. canvas_draw_icon(canvas, 28, 54, &I_ButtonOK_7x7);
  300. canvas_draw_str_aligned(canvas, 37, 54, AlignLeft, AlignTop, "UnFlip");
  301. } else if(!show_prev && show_next && is_flipped) {
  302. canvas_draw_icon(canvas, 0, 54, &I_ButtonRight_4x7);
  303. canvas_draw_str_aligned(canvas, 6, 54, AlignLeft, AlignTop, "Next");
  304. canvas_draw_icon(canvas, 28, 54, &I_ButtonOK_7x7);
  305. canvas_draw_str_aligned(canvas, 37, 54, AlignLeft, AlignTop, "UnFlip");
  306. } else if(!show_prev && !show_next && is_flipped) {
  307. canvas_draw_icon(canvas, 0, 54, &I_ButtonOK_7x7);
  308. canvas_draw_str_aligned(canvas, 9, 54, AlignLeft, AlignTop, "UnFlip");
  309. } else {
  310. canvas_draw_icon(canvas, 0, 54, &I_ButtonOK_7x7);
  311. canvas_draw_str_aligned(canvas, 9, 54, AlignLeft, AlignTop, "Flip");
  312. }
  313. }
  314. // Callback function to handle the feed dialog
  315. static void flip_social_callback_draw_feed(Canvas* canvas, void* model) {
  316. UNUSED(model);
  317. if(!canvas) {
  318. FURI_LOG_E(TAG, "Canvas is NULL");
  319. return;
  320. }
  321. if(!app_instance) {
  322. FURI_LOG_E(TAG, "FlipSocialApp is NULL");
  323. return;
  324. }
  325. if(!flip_social_dialog_shown) {
  326. flip_social_dialog_shown = true;
  327. app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
  328. app_instance->input_event =
  329. furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
  330. }
  331. // handle action
  332. switch(action) {
  333. case ActionNone:
  334. flip_social_canvas_draw_message(
  335. canvas,
  336. flip_social_feed->usernames[flip_social_feed->index],
  337. flip_social_feed->messages[flip_social_feed->index],
  338. flip_social_feed->is_flipped[flip_social_feed->index],
  339. flip_social_feed->index > 0,
  340. flip_social_feed->index < flip_social_feed->count - 1,
  341. flip_social_feed->flips[flip_social_feed->index]);
  342. break;
  343. case ActionNext:
  344. canvas_clear(canvas);
  345. if(flip_social_feed->index < flip_social_feed->count - 1) {
  346. flip_social_feed->index++;
  347. }
  348. flip_social_canvas_draw_message(
  349. canvas,
  350. flip_social_feed->usernames[flip_social_feed->index],
  351. flip_social_feed->messages[flip_social_feed->index],
  352. flip_social_feed->is_flipped[flip_social_feed->index],
  353. flip_social_feed->index > 0,
  354. flip_social_feed->index < flip_social_feed->count - 1,
  355. flip_social_feed->flips[flip_social_feed->index]);
  356. action = ActionNone;
  357. break;
  358. case ActionPrev:
  359. canvas_clear(canvas);
  360. if(flip_social_feed->index > 0) {
  361. flip_social_feed->index--;
  362. }
  363. flip_social_canvas_draw_message(
  364. canvas,
  365. flip_social_feed->usernames[flip_social_feed->index],
  366. flip_social_feed->messages[flip_social_feed->index],
  367. flip_social_feed->is_flipped[flip_social_feed->index],
  368. flip_social_feed->index > 0,
  369. flip_social_feed->index < flip_social_feed->count - 1,
  370. flip_social_feed->flips[flip_social_feed->index]);
  371. action = ActionNone;
  372. break;
  373. case ActionFlip:
  374. canvas_clear(canvas);
  375. // Moved to above the is_flipped check
  376. if(!flip_social_feed->is_flipped[flip_social_feed->index]) {
  377. // increase the flip count
  378. flip_social_feed->flips[flip_social_feed->index]++;
  379. } else {
  380. // decrease the flip count
  381. flip_social_feed->flips[flip_social_feed->index]--;
  382. }
  383. // change the flip status
  384. flip_social_feed->is_flipped[flip_social_feed->index] =
  385. !flip_social_feed->is_flipped[flip_social_feed->index];
  386. // send post request to flip the message
  387. if(app_instance->login_username_logged_in == NULL) {
  388. FURI_LOG_E(TAG, "Username is NULL");
  389. return;
  390. }
  391. char payload[256];
  392. snprintf(
  393. payload,
  394. sizeof(payload),
  395. "{\"username\":\"%s\",\"post_id\":\"%u\"}",
  396. app_instance->login_username_logged_in,
  397. flip_social_feed->ids[flip_social_feed->index]);
  398. flipper_http_post_request_with_headers(
  399. "https://www.flipsocial.net/api/feed/flip/",
  400. "{\"Content-Type\":\"application/json\"}",
  401. payload);
  402. flip_social_canvas_draw_message(
  403. canvas,
  404. flip_social_feed->usernames[flip_social_feed->index],
  405. flip_social_feed->messages[flip_social_feed->index],
  406. flip_social_feed->is_flipped[flip_social_feed->index],
  407. flip_social_feed->index > 0,
  408. flip_social_feed->index < flip_social_feed->count - 1,
  409. flip_social_feed->flips[flip_social_feed->index]);
  410. action = ActionNone;
  411. break;
  412. case ActionBack:
  413. canvas_clear(canvas);
  414. flip_social_dialog_stop = true;
  415. flip_social_feed->index = 0;
  416. action = ActionNone;
  417. break;
  418. default:
  419. break;
  420. }
  421. if(flip_social_dialog_stop) {
  422. furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
  423. flip_social_dialog_shown = false;
  424. flip_social_dialog_stop = false;
  425. action = ActionNone;
  426. }
  427. }
  428. /**
  429. * @brief Navigation callback for asynchonously handling the login process.
  430. * @param canvas The canvas to draw on.
  431. * @param model The model - unused
  432. * @return void
  433. */
  434. static void flip_social_callback_draw_login(Canvas* canvas, void* model) {
  435. UNUSED(model);
  436. if(!canvas) {
  437. FURI_LOG_E(TAG, "Canvas is NULL");
  438. return;
  439. }
  440. canvas_set_font(canvas, FontSecondary);
  441. if(!flip_social_board_is_active(canvas)) {
  442. return;
  443. }
  444. canvas_draw_str(canvas, 0, 7, "Logging in...");
  445. // Perform login request
  446. if(!flip_social_sent_login_request) {
  447. if(!app_instance->login_username_logged_out || !app_instance->login_password_logged_out ||
  448. strlen(app_instance->login_username_logged_out) == 0 ||
  449. strlen(app_instance->login_password_logged_out) == 0) {
  450. canvas_clear(canvas);
  451. canvas_draw_str(canvas, 0, 10, "Please enter your credentials.");
  452. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  453. return;
  454. }
  455. flip_social_sent_login_request = true;
  456. char buffer[256];
  457. snprintf(
  458. buffer,
  459. sizeof(buffer),
  460. "{\"username\":\"%s\",\"password\":\"%s\"}",
  461. app_instance->login_username_logged_out,
  462. app_instance->login_password_logged_out);
  463. flip_social_login_success = flipper_http_post_request_with_headers(
  464. "https://www.flipsocial.net/api/user/login/",
  465. "{\"Content-Type\":\"application/json\"}",
  466. buffer);
  467. if(flip_social_login_success) {
  468. fhttp.state = RECEIVING;
  469. return;
  470. } else {
  471. fhttp.state = ISSUE;
  472. return;
  473. }
  474. }
  475. // handle response
  476. if(flip_social_sent_login_request && flip_social_login_success) {
  477. canvas_set_font(canvas, FontSecondary);
  478. canvas_draw_str(canvas, 0, 17, "Request Sent!");
  479. canvas_draw_str(canvas, 0, 32, "Awaiting reponse...");
  480. if(fhttp.state == IDLE && fhttp.received_data != NULL) {
  481. // read response
  482. if(strstr(fhttp.received_data, "[SUCCESS]") != NULL ||
  483. strstr(fhttp.received_data, "User found") != NULL) {
  484. canvas_draw_str(canvas, 0, 42, "Login successful!");
  485. canvas_draw_str(canvas, 0, 62, "Welcome back!");
  486. app_instance->is_logged_in = "true";
  487. // set the logged_in_username and change_password_logged_in
  488. if(app_instance->login_username_logged_out) {
  489. strcpy(
  490. app_instance->login_username_logged_in,
  491. app_instance->login_username_logged_out);
  492. }
  493. if(app_instance->login_password_logged_out) {
  494. app_instance->change_password_logged_in =
  495. app_instance->login_password_logged_out;
  496. }
  497. save_settings(
  498. app_instance->wifi_ssid_logged_out,
  499. app_instance->wifi_password_logged_out,
  500. app_instance->login_username_logged_out,
  501. app_instance->login_username_logged_in,
  502. app_instance->login_password_logged_out,
  503. app_instance->change_password_logged_in,
  504. app_instance->is_logged_in);
  505. // send user to the logged in submenu
  506. view_dispatcher_switch_to_view(
  507. app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
  508. } else if(strstr(fhttp.received_data, "User not found") != NULL) {
  509. canvas_clear(canvas);
  510. canvas_draw_str(canvas, 0, 10, "Account not found...");
  511. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  512. } else {
  513. flip_social_handle_error(canvas);
  514. }
  515. } else if((fhttp.state == ISSUE || fhttp.state == INACTIVE) && fhttp.received_data != NULL) {
  516. flip_social_handle_error(canvas);
  517. } else if(fhttp.state == IDLE && fhttp.received_data == NULL) {
  518. flip_social_handle_error(canvas);
  519. }
  520. } else if(flip_social_sent_login_request && !flip_social_login_success) {
  521. canvas_clear(canvas);
  522. canvas_draw_str(canvas, 0, 10, "Failed sending request.");
  523. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  524. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  525. }
  526. }
  527. /**
  528. * @brief Navigation callback for asynchonously handling the register process.
  529. * @param canvas The canvas to draw on.
  530. * @param model The model - unused
  531. * @return void
  532. */
  533. static void flip_social_callback_draw_register(Canvas* canvas, void* model) {
  534. UNUSED(model);
  535. if(!canvas) {
  536. FURI_LOG_E(TAG, "Canvas is NULL");
  537. return;
  538. }
  539. canvas_set_font(canvas, FontSecondary);
  540. if(!flip_social_board_is_active(canvas)) {
  541. return;
  542. }
  543. canvas_draw_str(canvas, 0, 7, "Registering...");
  544. // Perform login request
  545. if(!flip_social_sent_register_request) {
  546. // check if the username and password are valid
  547. if(!app_instance->register_username_logged_out ||
  548. !app_instance->register_password_logged_out ||
  549. strlen(app_instance->register_username_logged_out) == 0 ||
  550. strlen(app_instance->register_password_logged_out) == 0) {
  551. canvas_clear(canvas);
  552. canvas_draw_str(canvas, 0, 10, "Please enter your credentials.");
  553. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  554. return;
  555. }
  556. // check if both passwords match
  557. if(strcmp(
  558. app_instance->register_password_logged_out,
  559. app_instance->register_password_2_logged_out) != 0) {
  560. canvas_clear(canvas);
  561. canvas_draw_str(canvas, 0, 10, "Passwords do not match.");
  562. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  563. return;
  564. }
  565. char buffer[128];
  566. snprintf(
  567. buffer,
  568. sizeof(buffer),
  569. "{\"username\":\"%s\",\"password\":\"%s\"}",
  570. app_instance->register_username_logged_out,
  571. app_instance->register_password_logged_out);
  572. flip_social_register_success = flipper_http_post_request_with_headers(
  573. "https://www.flipsocial.net/api/user/register/",
  574. "{\"Content-Type\":\"application/json\"}",
  575. buffer);
  576. flip_social_sent_register_request = true;
  577. if(flip_social_register_success) {
  578. // Set the state to RECEIVING to ensure we continue to see the receiving message
  579. fhttp.state = RECEIVING;
  580. } else {
  581. fhttp.state = ISSUE;
  582. }
  583. }
  584. // handle response
  585. if(flip_social_sent_register_request && flip_social_register_success) {
  586. canvas_set_font(canvas, FontSecondary);
  587. canvas_draw_str(canvas, 0, 17, "Request Sent!");
  588. canvas_draw_str(canvas, 0, 32, "Awaiting reponse...");
  589. if(fhttp.state == IDLE) {
  590. // read response
  591. if(fhttp.received_data != NULL &&
  592. (strstr(fhttp.received_data, "[SUCCESS]") != NULL ||
  593. strstr(fhttp.received_data, "User created") != NULL)) {
  594. canvas_draw_str(canvas, 0, 42, "Registeration successful!");
  595. canvas_draw_str(canvas, 0, 62, "Welcome to FlipSocial!");
  596. // set the login credentials
  597. if(app_instance->login_username_logged_out) {
  598. app_instance->login_username_logged_out =
  599. app_instance->register_username_logged_out;
  600. }
  601. if(app_instance->login_password_logged_out) {
  602. app_instance->login_password_logged_out =
  603. app_instance->register_password_logged_out;
  604. app_instance->change_password_logged_in =
  605. app_instance->register_password_logged_out;
  606. }
  607. if(app_instance->login_username_logged_in) {
  608. app_instance->login_username_logged_in =
  609. app_instance->register_username_logged_out;
  610. }
  611. app_instance->is_logged_in = "true";
  612. // save the credentials
  613. save_settings(
  614. app_instance->wifi_ssid_logged_out,
  615. app_instance->wifi_password_logged_out,
  616. app_instance->login_username_logged_out,
  617. app_instance->login_username_logged_in,
  618. app_instance->login_password_logged_out,
  619. app_instance->change_password_logged_in,
  620. app_instance->is_logged_in);
  621. // send user to the logged in submenu
  622. view_dispatcher_switch_to_view(
  623. app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
  624. } else if(strstr(fhttp.received_data, "Username or password not provided") != NULL) {
  625. canvas_clear(canvas);
  626. canvas_draw_str(canvas, 0, 10, "Please enter your credentials.");
  627. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  628. } else if(
  629. strstr(fhttp.received_data, "User already exists") != NULL ||
  630. strstr(fhttp.received_data, "Multiple users found") != NULL) {
  631. canvas_draw_str(canvas, 0, 42, "Registration failed...");
  632. canvas_draw_str(canvas, 0, 52, "Username already exists.");
  633. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  634. } else {
  635. canvas_draw_str(canvas, 0, 42, "Registration failed...");
  636. canvas_draw_str(canvas, 0, 52, "Update your credentials.");
  637. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  638. }
  639. } else if(fhttp.state == ISSUE || fhttp.state == INACTIVE) {
  640. flip_social_handle_error(canvas);
  641. }
  642. } else if(flip_social_sent_register_request && !flip_social_register_success) {
  643. canvas_clear(canvas);
  644. canvas_draw_str(canvas, 0, 10, "Failed sending request.");
  645. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  646. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  647. }
  648. }
  649. // function to draw the dialog canvas
  650. static void flip_social_canvas_draw_explore(Canvas* canvas, char* user_username, char* content) {
  651. canvas_set_color(canvas, ColorBlack);
  652. canvas_set_font(canvas, FontPrimary);
  653. canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, user_username);
  654. canvas_set_font(canvas, FontSecondary);
  655. draw_user_message(canvas, content, 0, 12);
  656. canvas_set_font(canvas, FontSecondary);
  657. canvas_draw_icon(canvas, 0, 53, &I_ButtonLeft_4x7);
  658. canvas_draw_str_aligned(canvas, 9, 54, AlignLeft, AlignTop, "Remove");
  659. canvas_draw_icon(canvas, 98, 53, &I_ButtonRight_4x7);
  660. canvas_draw_str_aligned(canvas, 107, 54, AlignLeft, AlignTop, "Add");
  661. if(strlen(content) > 0) {
  662. last_explore_response = content;
  663. }
  664. }
  665. // Callback function to handle the explore dialog
  666. static void flip_social_callback_draw_explore(Canvas* canvas, void* model) {
  667. UNUSED(model);
  668. if(!canvas) {
  669. FURI_LOG_E(TAG, "Canvas is NULL");
  670. return;
  671. }
  672. if(!app_instance) {
  673. FURI_LOG_E(TAG, "FlipSocialApp is NULL");
  674. return;
  675. }
  676. if(!flip_social_dialog_shown) {
  677. flip_social_dialog_shown = true;
  678. app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
  679. app_instance->input_event =
  680. furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
  681. }
  682. flip_social_canvas_draw_explore(
  683. canvas, flip_social_explore->usernames[flip_social_explore->index], last_explore_response);
  684. // handle action
  685. switch(action) {
  686. case ActionNext:
  687. // add friend
  688. char add_payload[128];
  689. snprintf(
  690. add_payload,
  691. sizeof(add_payload),
  692. "{\"username\":\"%s\",\"friend\":\"%s\"}",
  693. app_instance->login_username_logged_in,
  694. flip_social_explore->usernames[flip_social_explore->index]);
  695. flipper_http_post_request_with_headers(
  696. "https://www.flipsocial.net/api/user/add-friend/",
  697. "{\"Content-Type\":\"application/json\"}",
  698. add_payload);
  699. canvas_clear(canvas);
  700. flip_social_canvas_draw_explore(
  701. canvas, flip_social_explore->usernames[flip_social_explore->index], "Added!");
  702. action = ActionNone;
  703. break;
  704. case ActionPrev:
  705. // remove friend
  706. char remove_payload[128];
  707. snprintf(
  708. remove_payload,
  709. sizeof(remove_payload),
  710. "{\"username\":\"%s\",\"friend\":\"%s\"}",
  711. app_instance->login_username_logged_in,
  712. flip_social_explore->usernames[flip_social_explore->index]);
  713. flipper_http_post_request_with_headers(
  714. "https://www.flipsocial.net/api/user/remove-friend/",
  715. "{\"Content-Type\":\"application/json\"}",
  716. remove_payload);
  717. canvas_clear(canvas);
  718. flip_social_canvas_draw_explore(
  719. canvas, flip_social_explore->usernames[flip_social_explore->index], "Removed!");
  720. action = ActionNone;
  721. break;
  722. case ActionBack:
  723. canvas_clear(canvas);
  724. flip_social_dialog_stop = true;
  725. last_explore_response = "";
  726. flip_social_dialog_shown = false;
  727. flip_social_explore->index = 0;
  728. action = ActionNone;
  729. break;
  730. default:
  731. break;
  732. }
  733. if(flip_social_dialog_stop) {
  734. furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
  735. flip_social_dialog_shown = false;
  736. flip_social_dialog_stop = false;
  737. action = ActionNone;
  738. }
  739. }
  740. // Callback function to handle the friends dialog
  741. static void flip_social_callback_draw_friends(Canvas* canvas, void* model) {
  742. UNUSED(model);
  743. if(!canvas) {
  744. FURI_LOG_E(TAG, "Canvas is NULL");
  745. return;
  746. }
  747. if(!app_instance) {
  748. FURI_LOG_E(TAG, "FlipSocialApp is NULL");
  749. return;
  750. }
  751. if(!flip_social_dialog_shown) {
  752. flip_social_dialog_shown = true;
  753. app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
  754. app_instance->input_event =
  755. furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
  756. }
  757. flip_social_canvas_draw_explore(
  758. canvas, flip_social_friends->usernames[flip_social_friends->index], last_explore_response);
  759. // handle action
  760. switch(action) {
  761. case ActionNext:
  762. // add friend
  763. char add_payload[128];
  764. snprintf(
  765. add_payload,
  766. sizeof(add_payload),
  767. "{\"username\":\"%s\",\"friend\":\"%s\"}",
  768. app_instance->login_username_logged_in,
  769. flip_social_friends->usernames[flip_social_friends->index]);
  770. if(flipper_http_post_request_with_headers(
  771. "https://www.flipsocial.net/api/user/add-friend/",
  772. "{\"Content-Type\":\"application/json\"}",
  773. add_payload)) {
  774. canvas_clear(canvas);
  775. flip_social_canvas_draw_explore(
  776. canvas, flip_social_friends->usernames[flip_social_friends->index], "Added!");
  777. // add the friend to the friends list
  778. flip_social_friends->usernames[flip_social_friends->count] =
  779. flip_social_friends->usernames[flip_social_friends->index];
  780. flip_social_friends->count++;
  781. if(!flip_social_update_friends()) {
  782. FURI_LOG_E(TAG, "Failed to update friends");
  783. }
  784. }
  785. action = ActionNone;
  786. break;
  787. case ActionPrev:
  788. // remove friend
  789. char remove_payload[128];
  790. snprintf(
  791. remove_payload,
  792. sizeof(remove_payload),
  793. "{\"username\":\"%s\",\"friend\":\"%s\"}",
  794. app_instance->login_username_logged_in,
  795. flip_social_friends->usernames[flip_social_friends->index]);
  796. if(flipper_http_post_request_with_headers(
  797. "https://www.flipsocial.net/api/user/remove-friend/",
  798. "{\"Content-Type\":\"application/json\"}",
  799. remove_payload)) {
  800. canvas_clear(canvas);
  801. flip_social_canvas_draw_explore(
  802. canvas, flip_social_friends->usernames[flip_social_friends->index], "Removed!");
  803. // remove the friend from the friends list
  804. for(int i = flip_social_friends->index; i < flip_social_friends->count - 1; i++) {
  805. flip_social_friends->usernames[i] = flip_social_friends->usernames[i + 1];
  806. }
  807. flip_social_friends->count--;
  808. if(!flip_social_update_friends()) {
  809. FURI_LOG_E(TAG, "Failed to update friends");
  810. }
  811. }
  812. action = ActionNone;
  813. break;
  814. case ActionBack:
  815. canvas_clear(canvas);
  816. flip_social_dialog_stop = true;
  817. last_explore_response = "";
  818. flip_social_dialog_shown = false;
  819. flip_social_friends->index = 0;
  820. action = ActionNone;
  821. break;
  822. default:
  823. break;
  824. }
  825. if(flip_social_dialog_stop) {
  826. furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
  827. flip_social_dialog_shown = false;
  828. flip_social_dialog_stop = false;
  829. action = ActionNone;
  830. }
  831. }
  832. static void flip_social_canvas_draw_user_message(
  833. Canvas* canvas,
  834. char* user_username,
  835. char* user_message,
  836. bool show_prev,
  837. bool show_next) {
  838. canvas_set_color(canvas, ColorBlack);
  839. canvas_set_font(canvas, FontPrimary);
  840. canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, user_username);
  841. canvas_set_font(canvas, FontSecondary);
  842. draw_user_message(canvas, user_message, 0, 12);
  843. canvas_set_font(canvas, FontSecondary);
  844. if(show_prev) {
  845. canvas_draw_icon(canvas, 0, 53, &I_ButtonLeft_4x7);
  846. canvas_draw_str_aligned(canvas, 9, 54, AlignLeft, AlignTop, "Prev");
  847. }
  848. canvas_draw_icon(canvas, 47, 53, &I_ButtonOK_7x7);
  849. canvas_draw_str_aligned(canvas, 56, 54, AlignLeft, AlignTop, "Create");
  850. if(show_next) {
  851. canvas_draw_icon(canvas, 98, 53, &I_ButtonRight_4x7);
  852. canvas_draw_str_aligned(canvas, 107, 54, AlignLeft, AlignTop, "Next");
  853. }
  854. }
  855. // Callback function to handle the messages dialog
  856. static void flip_social_callback_draw_messages(Canvas* canvas, void* model) {
  857. UNUSED(model);
  858. if(!canvas) {
  859. FURI_LOG_E(TAG, "Canvas is NULL");
  860. return;
  861. }
  862. if(!app_instance) {
  863. FURI_LOG_E(TAG, "FlipSocialApp is NULL");
  864. return;
  865. }
  866. if(!flip_social_dialog_shown) {
  867. flip_social_dialog_shown = true;
  868. app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
  869. app_instance->input_event =
  870. furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
  871. }
  872. // handle action
  873. switch(action) {
  874. case ActionNone:
  875. flip_social_canvas_draw_user_message(
  876. canvas,
  877. flip_social_messages->usernames[flip_social_messages->index],
  878. flip_social_messages->messages[flip_social_messages->index],
  879. flip_social_messages->index > 0,
  880. flip_social_messages->index < flip_social_messages->count - 1);
  881. action = ActionNone;
  882. break;
  883. case ActionNext:
  884. // view next message (if any)
  885. canvas_clear(canvas);
  886. if(flip_social_messages->index < flip_social_messages->count - 1) {
  887. flip_social_messages->index++;
  888. }
  889. flip_social_canvas_draw_user_message(
  890. canvas,
  891. flip_social_messages->usernames[flip_social_messages->index],
  892. flip_social_messages->messages[flip_social_messages->index],
  893. flip_social_messages->index > 0,
  894. flip_social_messages->index < flip_social_messages->count - 1);
  895. action = ActionNone;
  896. break;
  897. case ActionPrev:
  898. // view previous message (if any)
  899. canvas_clear(canvas);
  900. if(flip_social_messages->index > 0) {
  901. flip_social_messages->index--;
  902. }
  903. flip_social_canvas_draw_user_message(
  904. canvas,
  905. flip_social_messages->usernames[flip_social_messages->index],
  906. flip_social_messages->messages[flip_social_messages->index],
  907. flip_social_messages->index > 0,
  908. flip_social_messages->index < flip_social_messages->count - 1);
  909. action = ActionNone;
  910. break;
  911. case ActionBack:
  912. // go back to the previous view
  913. flip_social_dialog_stop = true;
  914. action = ActionNone;
  915. break;
  916. case ActionFlip:
  917. // go to the input view
  918. flip_social_dialog_stop = true;
  919. break;
  920. default:
  921. action = ActionNone;
  922. break;
  923. }
  924. if(flip_social_dialog_stop) {
  925. furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
  926. flip_social_dialog_shown = false;
  927. flip_social_dialog_stop = false;
  928. if(action == ActionFlip) {
  929. action = ActionNone;
  930. view_dispatcher_switch_to_view(
  931. app_instance->view_dispatcher, FlipSocialViewLoggedInMessagesNewMessageInput);
  932. } else {
  933. action = ActionNone;
  934. view_dispatcher_switch_to_view(
  935. app_instance->view_dispatcher, FlipSocialViewLoggedInMessagesSubmenu);
  936. }
  937. }
  938. }
  939. #endif // FLIP_SOCIAL_DRAW_H