flip_social_draw.h 38 KB

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