flip_social_draw.h 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  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. // Moved to above the is_flipped check
  396. if (!flip_social_feed->is_flipped[flip_social_feed->index])
  397. {
  398. // increase the flip count
  399. flip_social_feed->flips[flip_social_feed->index]++;
  400. }
  401. else
  402. {
  403. // decrease the flip count
  404. flip_social_feed->flips[flip_social_feed->index]--;
  405. }
  406. // change the flip status
  407. flip_social_feed->is_flipped[flip_social_feed->index] = !flip_social_feed->is_flipped[flip_social_feed->index];
  408. // send post request to flip the message
  409. if (app_instance->login_username_logged_in == NULL)
  410. {
  411. FURI_LOG_E(TAG, "Username is NULL");
  412. return;
  413. }
  414. char payload[256];
  415. snprintf(payload, sizeof(payload), "{\"username\":\"%s\",\"post_id\":\"%u\"}", app_instance->login_username_logged_in, flip_social_feed->ids[flip_social_feed->index]);
  416. flipper_http_post_request_with_headers("https://www.flipsocial.net/api/feed/flip/", "{\"Content-Type\":\"application/json\"}", payload);
  417. 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]);
  418. action = ActionNone;
  419. break;
  420. case ActionBack:
  421. canvas_clear(canvas);
  422. flip_social_dialog_stop = true;
  423. flip_social_feed->index = 0;
  424. action = ActionNone;
  425. break;
  426. default:
  427. break;
  428. }
  429. if (flip_social_dialog_stop)
  430. {
  431. furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
  432. flip_social_dialog_shown = false;
  433. flip_social_dialog_stop = false;
  434. action = ActionNone;
  435. }
  436. }
  437. /**
  438. * @brief Navigation callback for asynchonously handling the login process.
  439. * @param canvas The canvas to draw on.
  440. * @param model The model - unused
  441. * @return void
  442. */
  443. static void flip_social_callback_draw_login(Canvas *canvas, void *model)
  444. {
  445. UNUSED(model);
  446. if (!canvas)
  447. {
  448. FURI_LOG_E(TAG, "Canvas is NULL");
  449. return;
  450. }
  451. canvas_set_font(canvas, FontSecondary);
  452. if (!flip_social_board_is_active(canvas))
  453. {
  454. return;
  455. }
  456. canvas_draw_str(canvas, 0, 7, "Logging in...");
  457. // Perform login request
  458. if (!flip_social_sent_login_request)
  459. {
  460. 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)
  461. {
  462. canvas_clear(canvas);
  463. canvas_draw_str(canvas, 0, 10, "Please enter your credentials.");
  464. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  465. return;
  466. }
  467. flip_social_sent_login_request = true;
  468. char buffer[256];
  469. snprintf(buffer, sizeof(buffer), "{\"username\":\"%s\",\"password\":\"%s\"}", app_instance->login_username_logged_out, app_instance->login_password_logged_out);
  470. flip_social_login_success = flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/login/", "{\"Content-Type\":\"application/json\"}", buffer);
  471. if (flip_social_login_success)
  472. {
  473. fhttp.state = RECEIVING;
  474. return;
  475. }
  476. else
  477. {
  478. fhttp.state = ISSUE;
  479. return;
  480. }
  481. }
  482. // handle response
  483. if (flip_social_sent_login_request && flip_social_login_success)
  484. {
  485. canvas_set_font(canvas, FontSecondary);
  486. canvas_draw_str(canvas, 0, 17, "Request Sent!");
  487. canvas_draw_str(canvas, 0, 32, "Awaiting reponse...");
  488. if (fhttp.state == IDLE && fhttp.received_data != NULL)
  489. {
  490. // read response
  491. if (strstr(fhttp.received_data, "[SUCCESS]") != NULL || strstr(fhttp.received_data, "User found") != NULL)
  492. {
  493. canvas_draw_str(canvas, 0, 42, "Login successful!");
  494. canvas_draw_str(canvas, 0, 62, "Welcome back!");
  495. app_instance->is_logged_in = "true";
  496. // set the logged_in_username and change_password_logged_in
  497. if (app_instance->login_username_logged_out)
  498. {
  499. strcpy(app_instance->login_username_logged_in, app_instance->login_username_logged_out);
  500. }
  501. if (app_instance->login_password_logged_out)
  502. {
  503. app_instance->change_password_logged_in = app_instance->login_password_logged_out;
  504. }
  505. 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);
  506. // send user to the logged in submenu
  507. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
  508. }
  509. else if (strstr(fhttp.received_data, "User not found") != NULL)
  510. {
  511. canvas_clear(canvas);
  512. canvas_draw_str(canvas, 0, 10, "Account not found...");
  513. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  514. }
  515. else
  516. {
  517. flip_social_handle_error(canvas);
  518. }
  519. }
  520. else if ((fhttp.state == ISSUE || fhttp.state == INACTIVE) && fhttp.received_data != NULL)
  521. {
  522. flip_social_handle_error(canvas);
  523. }
  524. else if (fhttp.state == IDLE && fhttp.received_data == NULL)
  525. {
  526. flip_social_handle_error(canvas);
  527. }
  528. }
  529. else if (flip_social_sent_login_request && !flip_social_login_success)
  530. {
  531. canvas_clear(canvas);
  532. canvas_draw_str(canvas, 0, 10, "Failed sending request.");
  533. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  534. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  535. }
  536. }
  537. /**
  538. * @brief Navigation callback for asynchonously handling the register process.
  539. * @param canvas The canvas to draw on.
  540. * @param model The model - unused
  541. * @return void
  542. */
  543. static void flip_social_callback_draw_register(Canvas *canvas, void *model)
  544. {
  545. UNUSED(model);
  546. if (!canvas)
  547. {
  548. FURI_LOG_E(TAG, "Canvas is NULL");
  549. return;
  550. }
  551. canvas_set_font(canvas, FontSecondary);
  552. if (!flip_social_board_is_active(canvas))
  553. {
  554. return;
  555. }
  556. canvas_draw_str(canvas, 0, 7, "Registering...");
  557. // Perform login request
  558. if (!flip_social_sent_register_request)
  559. {
  560. // check if the username and password are valid
  561. 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)
  562. {
  563. canvas_clear(canvas);
  564. canvas_draw_str(canvas, 0, 10, "Please enter your credentials.");
  565. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  566. return;
  567. }
  568. // check if both passwords match
  569. if (strcmp(app_instance->register_password_logged_out, app_instance->register_password_2_logged_out) != 0)
  570. {
  571. canvas_clear(canvas);
  572. canvas_draw_str(canvas, 0, 10, "Passwords do not match.");
  573. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  574. return;
  575. }
  576. char buffer[128];
  577. snprintf(buffer, sizeof(buffer), "{\"username\":\"%s\",\"password\":\"%s\"}", app_instance->register_username_logged_out, app_instance->register_password_logged_out);
  578. flip_social_register_success = flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/register/", "{\"Content-Type\":\"application/json\"}", buffer);
  579. flip_social_sent_register_request = true;
  580. if (flip_social_register_success)
  581. {
  582. // Set the state to RECEIVING to ensure we continue to see the receiving message
  583. fhttp.state = RECEIVING;
  584. }
  585. else
  586. {
  587. fhttp.state = ISSUE;
  588. }
  589. }
  590. // handle response
  591. if (flip_social_sent_register_request && flip_social_register_success)
  592. {
  593. canvas_set_font(canvas, FontSecondary);
  594. canvas_draw_str(canvas, 0, 17, "Request Sent!");
  595. canvas_draw_str(canvas, 0, 32, "Awaiting reponse...");
  596. if (fhttp.state == IDLE)
  597. {
  598. // read response
  599. if (fhttp.received_data != NULL && (strstr(fhttp.received_data, "[SUCCESS]") != NULL || strstr(fhttp.received_data, "User created") != NULL))
  600. {
  601. canvas_draw_str(canvas, 0, 42, "Registeration successful!");
  602. canvas_draw_str(canvas, 0, 62, "Welcome to FlipSocial!");
  603. // set the login credentials
  604. if (app_instance->login_username_logged_out)
  605. {
  606. app_instance->login_username_logged_out = app_instance->register_username_logged_out;
  607. }
  608. if (app_instance->login_password_logged_out)
  609. {
  610. app_instance->login_password_logged_out = app_instance->register_password_logged_out;
  611. app_instance->change_password_logged_in = app_instance->register_password_logged_out;
  612. }
  613. if (app_instance->login_username_logged_in)
  614. {
  615. app_instance->login_username_logged_in = app_instance->register_username_logged_out;
  616. }
  617. app_instance->is_logged_in = "true";
  618. // save the credentials
  619. 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);
  620. // send user to the logged in submenu
  621. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
  622. }
  623. else if (strstr(fhttp.received_data, "Username or password not provided") != NULL)
  624. {
  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. }
  629. else if (strstr(fhttp.received_data, "User already exists") != NULL || strstr(fhttp.received_data, "Multiple users found") != NULL)
  630. {
  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. }
  635. else
  636. {
  637. canvas_draw_str(canvas, 0, 42, "Registration failed...");
  638. canvas_draw_str(canvas, 0, 52, "Update your credentials.");
  639. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  640. }
  641. }
  642. else if (fhttp.state == ISSUE || fhttp.state == INACTIVE)
  643. {
  644. flip_social_handle_error(canvas);
  645. }
  646. }
  647. else if (flip_social_sent_register_request && !flip_social_register_success)
  648. {
  649. canvas_clear(canvas);
  650. canvas_draw_str(canvas, 0, 10, "Failed sending request.");
  651. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  652. canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
  653. }
  654. }
  655. // function to draw the dialog canvas
  656. static void flip_social_canvas_draw_explore(Canvas *canvas, char *user_username, char *content)
  657. {
  658. canvas_set_color(canvas, ColorBlack);
  659. canvas_set_font(canvas, FontPrimary);
  660. canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, user_username);
  661. canvas_set_font(canvas, FontSecondary);
  662. draw_user_message(canvas, content, 0, 12);
  663. canvas_set_font(canvas, FontSecondary);
  664. canvas_draw_icon(canvas, 0, 53, &I_ButtonLeft_4x7);
  665. canvas_draw_str_aligned(canvas, 9, 54, AlignLeft, AlignTop, "Remove");
  666. canvas_draw_icon(canvas, 98, 53, &I_ButtonRight_4x7);
  667. canvas_draw_str_aligned(canvas, 107, 54, AlignLeft, AlignTop, "Add");
  668. if (strlen(content) > 0)
  669. {
  670. last_explore_response = content;
  671. }
  672. }
  673. // Callback function to handle the explore dialog
  674. static void flip_social_callback_draw_explore(Canvas *canvas, void *model)
  675. {
  676. UNUSED(model);
  677. if (!canvas)
  678. {
  679. FURI_LOG_E(TAG, "Canvas is NULL");
  680. return;
  681. }
  682. if (!app_instance)
  683. {
  684. FURI_LOG_E(TAG, "FlipSocialApp is NULL");
  685. return;
  686. }
  687. if (!flip_social_dialog_shown)
  688. {
  689. flip_social_dialog_shown = true;
  690. app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
  691. app_instance->input_event = furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
  692. }
  693. flip_social_canvas_draw_explore(canvas, flip_social_explore->usernames[flip_social_explore->index], last_explore_response);
  694. // handle action
  695. switch (action)
  696. {
  697. case ActionNext:
  698. // add friend
  699. char add_payload[128];
  700. snprintf(add_payload, sizeof(add_payload), "{\"username\":\"%s\",\"friend\":\"%s\"}", app_instance->login_username_logged_in, flip_social_explore->usernames[flip_social_explore->index]);
  701. flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/add-friend/", "{\"Content-Type\":\"application/json\"}", add_payload);
  702. canvas_clear(canvas);
  703. flip_social_canvas_draw_explore(canvas, flip_social_explore->usernames[flip_social_explore->index], "Added!");
  704. action = ActionNone;
  705. break;
  706. case ActionPrev:
  707. // remove friend
  708. char remove_payload[128];
  709. snprintf(remove_payload, sizeof(remove_payload), "{\"username\":\"%s\",\"friend\":\"%s\"}", app_instance->login_username_logged_in, flip_social_explore->usernames[flip_social_explore->index]);
  710. flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/remove-friend/", "{\"Content-Type\":\"application/json\"}", remove_payload);
  711. canvas_clear(canvas);
  712. flip_social_canvas_draw_explore(canvas, flip_social_explore->usernames[flip_social_explore->index], "Removed!");
  713. action = ActionNone;
  714. break;
  715. case ActionBack:
  716. canvas_clear(canvas);
  717. flip_social_dialog_stop = true;
  718. last_explore_response = "";
  719. flip_social_dialog_shown = false;
  720. flip_social_explore->index = 0;
  721. action = ActionNone;
  722. break;
  723. default:
  724. break;
  725. }
  726. if (flip_social_dialog_stop)
  727. {
  728. furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
  729. flip_social_dialog_shown = false;
  730. flip_social_dialog_stop = false;
  731. action = ActionNone;
  732. }
  733. }
  734. // Callback function to handle the friends dialog
  735. static void flip_social_callback_draw_friends(Canvas *canvas, void *model)
  736. {
  737. UNUSED(model);
  738. if (!canvas)
  739. {
  740. FURI_LOG_E(TAG, "Canvas is NULL");
  741. return;
  742. }
  743. if (!app_instance)
  744. {
  745. FURI_LOG_E(TAG, "FlipSocialApp is NULL");
  746. return;
  747. }
  748. if (!flip_social_dialog_shown)
  749. {
  750. flip_social_dialog_shown = true;
  751. app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
  752. app_instance->input_event = furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
  753. }
  754. flip_social_canvas_draw_explore(canvas, flip_social_friends->usernames[flip_social_friends->index], last_explore_response);
  755. // handle action
  756. switch (action)
  757. {
  758. case ActionNext:
  759. // add friend
  760. char add_payload[128];
  761. snprintf(add_payload, sizeof(add_payload), "{\"username\":\"%s\",\"friend\":\"%s\"}", app_instance->login_username_logged_in, flip_social_friends->usernames[flip_social_friends->index]);
  762. if (flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/add-friend/", "{\"Content-Type\":\"application/json\"}", add_payload))
  763. {
  764. canvas_clear(canvas);
  765. flip_social_canvas_draw_explore(canvas, flip_social_friends->usernames[flip_social_friends->index], "Added!");
  766. // add the friend to the friends list
  767. flip_social_friends->usernames[flip_social_friends->count] = flip_social_friends->usernames[flip_social_friends->index];
  768. flip_social_friends->count++;
  769. if (!flip_social_update_friends())
  770. {
  771. FURI_LOG_E(TAG, "Failed to update friends");
  772. }
  773. }
  774. action = ActionNone;
  775. break;
  776. case ActionPrev:
  777. // remove friend
  778. char remove_payload[128];
  779. snprintf(remove_payload, sizeof(remove_payload), "{\"username\":\"%s\",\"friend\":\"%s\"}", app_instance->login_username_logged_in, flip_social_friends->usernames[flip_social_friends->index]);
  780. if (flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/remove-friend/", "{\"Content-Type\":\"application/json\"}", remove_payload))
  781. {
  782. canvas_clear(canvas);
  783. flip_social_canvas_draw_explore(canvas, flip_social_friends->usernames[flip_social_friends->index], "Removed!");
  784. // remove the friend from the friends list
  785. for (int i = flip_social_friends->index; i < flip_social_friends->count - 1; i++)
  786. {
  787. flip_social_friends->usernames[i] = flip_social_friends->usernames[i + 1];
  788. }
  789. flip_social_friends->count--;
  790. if (!flip_social_update_friends())
  791. {
  792. FURI_LOG_E(TAG, "Failed to update friends");
  793. }
  794. }
  795. action = ActionNone;
  796. break;
  797. case ActionBack:
  798. canvas_clear(canvas);
  799. flip_social_dialog_stop = true;
  800. last_explore_response = "";
  801. flip_social_dialog_shown = false;
  802. flip_social_friends->index = 0;
  803. action = ActionNone;
  804. break;
  805. default:
  806. break;
  807. }
  808. if (flip_social_dialog_stop)
  809. {
  810. furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
  811. flip_social_dialog_shown = false;
  812. flip_social_dialog_stop = false;
  813. action = ActionNone;
  814. }
  815. }
  816. static void flip_social_canvas_draw_user_message(Canvas *canvas, char *user_username, char *user_message, bool show_prev, bool show_next)
  817. {
  818. canvas_set_color(canvas, ColorBlack);
  819. canvas_set_font(canvas, FontPrimary);
  820. canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, user_username);
  821. canvas_set_font(canvas, FontSecondary);
  822. draw_user_message(canvas, user_message, 0, 12);
  823. canvas_set_font(canvas, FontSecondary);
  824. if (show_prev)
  825. {
  826. canvas_draw_icon(canvas, 0, 53, &I_ButtonLeft_4x7);
  827. canvas_draw_str_aligned(canvas, 9, 54, AlignLeft, AlignTop, "Prev");
  828. }
  829. canvas_draw_icon(canvas, 47, 53, &I_ButtonOK_7x7);
  830. canvas_draw_str_aligned(canvas, 56, 54, AlignLeft, AlignTop, "Create");
  831. if (show_next)
  832. {
  833. canvas_draw_icon(canvas, 98, 53, &I_ButtonRight_4x7);
  834. canvas_draw_str_aligned(canvas, 107, 54, AlignLeft, AlignTop, "Next");
  835. }
  836. }
  837. // Callback function to handle the messages dialog
  838. static void flip_social_callback_draw_messages(Canvas *canvas, void *model)
  839. {
  840. UNUSED(model);
  841. if (!canvas)
  842. {
  843. FURI_LOG_E(TAG, "Canvas is NULL");
  844. return;
  845. }
  846. if (!app_instance)
  847. {
  848. FURI_LOG_E(TAG, "FlipSocialApp is NULL");
  849. return;
  850. }
  851. if (!flip_social_dialog_shown)
  852. {
  853. flip_social_dialog_shown = true;
  854. app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
  855. app_instance->input_event = furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
  856. }
  857. // handle action
  858. switch (action)
  859. {
  860. case ActionNone:
  861. 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);
  862. action = ActionNone;
  863. break;
  864. case ActionNext:
  865. // view next message (if any)
  866. canvas_clear(canvas);
  867. if (flip_social_messages->index < flip_social_messages->count - 1)
  868. {
  869. flip_social_messages->index++;
  870. }
  871. 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);
  872. action = ActionNone;
  873. break;
  874. case ActionPrev:
  875. // view previous message (if any)
  876. canvas_clear(canvas);
  877. if (flip_social_messages->index > 0)
  878. {
  879. flip_social_messages->index--;
  880. }
  881. 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);
  882. action = ActionNone;
  883. break;
  884. case ActionBack:
  885. // go back to the previous view
  886. flip_social_dialog_stop = true;
  887. action = ActionNone;
  888. break;
  889. case ActionFlip:
  890. // go to the input view
  891. flip_social_dialog_stop = true;
  892. break;
  893. default:
  894. action = ActionNone;
  895. break;
  896. }
  897. if (flip_social_dialog_stop)
  898. {
  899. furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
  900. flip_social_dialog_shown = false;
  901. flip_social_dialog_stop = false;
  902. if (action == ActionFlip)
  903. {
  904. action = ActionNone;
  905. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInMessagesNewMessageInput);
  906. }
  907. else
  908. {
  909. action = ActionNone;
  910. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInMessagesSubmenu);
  911. }
  912. }
  913. }
  914. #endif // FLIP_SOCIAL_DRAW_H