Add saved GIF picker and docs
All checks were successful
Release App / release-app (push) Successful in 46s
All checks were successful
Release App / release-app (push) Successful in 46s
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <clocale>
|
||||
#include <sstream>
|
||||
|
||||
#include <curses.h>
|
||||
|
||||
@@ -28,6 +29,22 @@ std::string truncate_to_width(std::string text, int max_width) {
|
||||
return text;
|
||||
}
|
||||
|
||||
std::vector<std::string> split_preview_lines(const std::string &text) {
|
||||
std::vector<std::string> lines;
|
||||
std::stringstream stream(text);
|
||||
std::string line;
|
||||
while (std::getline(stream, line)) {
|
||||
if (!line.empty() && line.back() == '\r') {
|
||||
line.pop_back();
|
||||
}
|
||||
lines.push_back(line);
|
||||
}
|
||||
if (lines.empty()) {
|
||||
lines.push_back(text);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void App::init_curses() {
|
||||
@@ -150,6 +167,9 @@ void App::draw() {
|
||||
draw_attachment_viewer(height, width);
|
||||
} else if (attachment_action_menu_open_) {
|
||||
draw_attachment_action_menu(height, width);
|
||||
} else if (saved_animation_menu_open_) {
|
||||
clear_attachment_preview_graphics();
|
||||
draw_saved_animation_menu(height, width);
|
||||
} else if (attachments_menu_open_) {
|
||||
draw_attachments_menu(height, width);
|
||||
} else if (forward_target_menu_open_) {
|
||||
@@ -249,6 +269,116 @@ void App::draw_forward_target_menu(int height, int width) {
|
||||
delwin(window);
|
||||
}
|
||||
|
||||
void App::draw_saved_animation_menu(int height, int width) {
|
||||
const int menu_width = std::min(width - 4, 110);
|
||||
const int menu_height = std::min(height - 4, 28);
|
||||
const int top = std::max(1, (height - menu_height) / 2);
|
||||
const int left = std::max(1, (width - menu_width) / 2);
|
||||
|
||||
WINDOW *window = newwin(menu_height, menu_width, top, left);
|
||||
if (window == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (saved_animation_selection_index_ < 0) {
|
||||
saved_animation_selection_index_ = 0;
|
||||
}
|
||||
if (saved_animation_selection_index_ >= static_cast<int>(saved_animations_.size())) {
|
||||
saved_animation_selection_index_ =
|
||||
std::max(0, static_cast<int>(saved_animations_.size()) - 1);
|
||||
}
|
||||
|
||||
box(window, 0, 0);
|
||||
mvwprintw(window, 0, 2, " Saved GIFs ");
|
||||
std::string subtitle = saved_animations_loading_
|
||||
? "Loading..."
|
||||
: std::to_string(saved_animations_.size()) + " saved";
|
||||
mvwaddnstr(window, 1, 2, subtitle.c_str(), menu_width - 4);
|
||||
mvwhline(window, 2, 1, ACS_HLINE, menu_width - 2);
|
||||
|
||||
const int list_width = std::max(28, menu_width / 2 - 1);
|
||||
const int preview_left = list_width + 2;
|
||||
const int preview_width = std::max(10, menu_width - preview_left - 2);
|
||||
const int list_top = 3;
|
||||
const int list_height = std::max(1, menu_height - 6);
|
||||
int first_index = 0;
|
||||
if (saved_animation_selection_index_ >= list_height) {
|
||||
first_index = saved_animation_selection_index_ - list_height + 1;
|
||||
}
|
||||
|
||||
for (int row = 0; row < list_height; ++row) {
|
||||
const int item_index = first_index + row;
|
||||
const int y = list_top + row;
|
||||
mvwhline(window, y, 1, ' ', list_width);
|
||||
if (item_index >= static_cast<int>(saved_animations_.size())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const SavedAnimationInfo &animation =
|
||||
saved_animations_[static_cast<std::size_t>(item_index)];
|
||||
std::string label = animation.name;
|
||||
if (animation.is_downloading_active && !animation.is_downloaded) {
|
||||
label += " [dl]";
|
||||
} else if (animation.is_downloaded) {
|
||||
label += " [ready]";
|
||||
}
|
||||
if (item_index == saved_animation_selection_index_) {
|
||||
wattron(window, A_REVERSE | A_BOLD);
|
||||
}
|
||||
mvwaddnstr(window, y, 2, truncate_to_width(label, list_width - 2).c_str(),
|
||||
list_width - 2);
|
||||
if (item_index == saved_animation_selection_index_) {
|
||||
wattroff(window, A_REVERSE | A_BOLD);
|
||||
}
|
||||
}
|
||||
|
||||
mvwvline(window, 3, preview_left - 1, ACS_VLINE, menu_height - 4);
|
||||
|
||||
if (saved_animations_.empty()) {
|
||||
mvwaddnstr(window, 4, preview_left, "No saved GIFs on this account.", preview_width);
|
||||
} else {
|
||||
const SavedAnimationInfo &animation = saved_animations_[static_cast<std::size_t>(
|
||||
saved_animation_selection_index_)];
|
||||
const std::string title = truncate_to_width(animation.name, preview_width);
|
||||
mvwaddnstr(window, 3, preview_left, title.c_str(), preview_width);
|
||||
const std::string meta =
|
||||
truncate_to_width(format_file_size(animation.size_bytes) + " " +
|
||||
std::to_string(std::max(0, animation.width)) + "x" +
|
||||
std::to_string(std::max(0, animation.height)) + " " +
|
||||
std::to_string(std::max(0, animation.duration)) + "s",
|
||||
preview_width);
|
||||
mvwaddnstr(window, 4, preview_left, meta.c_str(), preview_width);
|
||||
mvwhline(window, 5, preview_left, ACS_HLINE, preview_width);
|
||||
|
||||
AttachmentInfo preview_attachment;
|
||||
preview_attachment.type = AttachmentType::Animation;
|
||||
preview_attachment.name = animation.name;
|
||||
preview_attachment.size_bytes = animation.size_bytes;
|
||||
preview_attachment.downloaded_size = animation.downloaded_size;
|
||||
preview_attachment.file_id = animation.file_id;
|
||||
preview_attachment.local_path = animation.local_path;
|
||||
preview_attachment.is_downloading_active = animation.is_downloading_active;
|
||||
preview_attachment.can_be_downloaded = animation.can_be_downloaded;
|
||||
preview_attachment.can_be_deleted = animation.can_be_deleted;
|
||||
preview_attachment.is_downloaded = animation.is_downloaded;
|
||||
|
||||
const std::string preview = render_attachment_preview(
|
||||
preview_attachment, preview_width, std::max(4, list_height - 4));
|
||||
const std::vector<std::string> preview_lines = split_preview_lines(preview);
|
||||
for (std::size_t i = 0; i < preview_lines.size() &&
|
||||
static_cast<int>(i) < list_height - 3;
|
||||
++i) {
|
||||
mvwaddnstr(window, 6 + static_cast<int>(i), preview_left,
|
||||
truncate_to_width(preview_lines[i], preview_width).c_str(), preview_width);
|
||||
}
|
||||
}
|
||||
|
||||
mvwaddnstr(window, menu_height - 2, 2,
|
||||
"Enter send r refresh Up/Down move Esc close", menu_width - 4);
|
||||
wrefresh(window);
|
||||
delwin(window);
|
||||
}
|
||||
|
||||
std::string App::current_auth_label() const {
|
||||
const std::string type = safe_string(authorization_state_, "@type");
|
||||
if (type == "authorizationStateWaitTdlibParameters") {
|
||||
|
||||
Reference in New Issue
Block a user