Skip to content

Commit

Permalink
gui: Refactor notice handling and app selection.
Browse files Browse the repository at this point in the history
- Switch from opening app to selecting it for newly installed apps.
- Implement erase app notice when corresponding app is deleted.
- Refactor structures to remove redundant variables.
  • Loading branch information
Zangetsu38 committed Oct 10, 2024
1 parent 93759d9 commit bfe9368
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 46 deletions.
2 changes: 2 additions & 0 deletions vita3k/gui/include/gui/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void close_and_run_new_app(GuiState &gui, EmuEnvState &emuenv, const std::string
void close_live_area_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path);
void close_system_app(GuiState &gui, EmuEnvState &emuenv);
void delete_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path);
void erase_app_notice(GuiState &gui, const std::string &title_id);
void get_app_info(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path);
size_t get_app_size(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path);
App *get_app_index(GuiState &gui, const std::string &app_path);
Expand Down Expand Up @@ -101,6 +102,7 @@ void pre_run_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path
void reset_controller_binding(EmuEnvState &emuenv);
void save_apps_cache(GuiState &gui, EmuEnvState &emuenv);
void save_user(GuiState &gui, EmuEnvState &emuenv, const std::string &user_id);
void select_app(GuiState &gui, const std::string &title_id);
void set_config(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path);
void set_shaders_compiled_display(GuiState &gui, EmuEnvState &emuenv);
void update_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path);
Expand Down
3 changes: 3 additions & 0 deletions vita3k/gui/src/app_context_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ void delete_app(GuiState &gui, EmuEnvState &emuenv, const std::string &app_path)
save_time_apps(gui, emuenv);
}

erase_app_notice(gui, title_id);
save_notice_list(emuenv);

LOG_INFO("Application successfully deleted '{} [{}]'.", title_id, APP_INDEX->title);

gui.app_selector.user_apps.erase(gui.app_selector.user_apps.begin() + (APP_INDEX - &gui.app_selector.user_apps[0]));
Expand Down
3 changes: 2 additions & 1 deletion vita3k/gui/src/archive_install_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,10 @@ void draw_archive_install_dialog(GuiState &gui, EmuEnvState &emuenv) {
emuenv.app_info.app_content_id = content.content_id;
if (emuenv.app_info.app_category != "theme")
update_notice_info(gui, emuenv, "content");
if (content.category == "gd") {
if ((content.category.find("gd") != std::string::npos) || (content.category.find("gp") != std::string::npos)) {
init_user_app(gui, emuenv, content.title_id);
save_apps_cache(gui, emuenv);
select_app(gui, content.title_id);
}
}
}
Expand Down
42 changes: 29 additions & 13 deletions vita3k/gui/src/home_screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,9 @@ static std::string get_label_name(GuiState &gui, const SortType &type) {
return label;
}

static int32_t first_visible_app_index = -4, current_selected_app_index = -5;
static constexpr int32_t INVALID_APP_INDEX = -5;
static int32_t first_visible_app_index = INVALID_APP_INDEX, current_selected_app_index = INVALID_APP_INDEX;

static std::vector<int32_t> apps_list_filtered;
void browse_home_apps_list(GuiState &gui, EmuEnvState &emuenv, const uint32_t button) {
if (apps_list_filtered.empty())
Expand All @@ -430,7 +432,7 @@ void browse_home_apps_list(GuiState &gui, EmuEnvState &emuenv, const uint32_t bu
gui.is_nav_button = true;

// When the current selected app index have not any selected, set it to the first visible app index
if (current_selected_app_index < -4)
if (current_selected_app_index <= INVALID_APP_INDEX)
current_selected_app_index = first_visible_app_index;

return;
Expand Down Expand Up @@ -505,6 +507,22 @@ void browse_home_apps_list(GuiState &gui, EmuEnvState &emuenv, const uint32_t bu
}
}

static int selected_app_index = INVALID_APP_INDEX;
void select_app(GuiState &gui, const std::string &title_id) {
// Find the app in the user apps list
auto app_it = std::find_if(gui.app_selector.user_apps.begin(), gui.app_selector.user_apps.end(), [&](const App &app) {
return app.title_id == title_id;
});

// Check if the app was found
if (app_it != gui.app_selector.user_apps.end()) {
// Set the selected app index
current_selected_app_index = selected_app_index = std::distance(gui.app_selector.user_apps.begin(), app_it);
gui.is_nav_button = true;
} else
LOG_ERROR("App with title id {} not found", title_id);
}

static constexpr ImU32 ARROW_COLOR = 0xFFFFFFFF; // White
static float scroll_type, current_scroll_pos, max_scroll_pos;

Expand Down Expand Up @@ -757,7 +775,6 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) {

const auto display_app = [&](const std::vector<gui::App> &apps_list, std::map<std::string, ImGui_Texture> &apps_icon) {
for (const auto &app : apps_list) {
bool selected = false;
const auto is_sys = app.path.starts_with("NPXS") && (app.path != "NPXS10007");

if (!is_sys) {
Expand All @@ -784,18 +801,19 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) {
ImGui::SetCursorPosX(GRID_ICON_POS);

// Get the current app index off the apps list.
const auto app_index = static_cast<int>(&app - &apps_list[0]);
const auto app_index = static_cast<int>(&app - apps_list.data());
const auto current_app_index = !is_sys ? app_index : app_index - 4;
apps_list_filtered.push_back(current_app_index);

// Check if the current app is selected.
const auto is_app_selected = gui.is_nav_button && (current_selected_app_index == current_app_index);

const auto is_current_app_selected = gui.is_nav_button && (current_selected_app_index == current_app_index);
const auto icon_flags = emuenv.cfg.apps_list_grid ? ImGuiSelectableFlags_None : ImGuiSelectableFlags_SpanAllColumns;
if (ImGui::Selectable("##icon", selected || is_app_selected, icon_flags, SELECTABLE_APP_SIZE))
selected = true;
if (ImGui::Selectable("##icon", is_current_app_selected || (selected_app_index == current_app_index), icon_flags, SELECTABLE_APP_SIZE)) {
selected_app_index = INVALID_APP_INDEX;
pre_load_app(gui, emuenv, emuenv.cfg.show_live_area_screen, app.path);
}

if (!gui.configuration_menu.custom_settings_dialog && (ImGui::IsItemHovered() || is_app_selected))
if (!gui.configuration_menu.custom_settings_dialog && (ImGui::IsItemHovered() || is_current_app_selected))
emuenv.app_path = app.path;
if (emuenv.app_path == app.path)
draw_app_context_menu(gui, emuenv, app.path);
Expand All @@ -813,7 +831,7 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) {
const auto element_is_within_visible_area = (MIN_ITEM_RECT_MAX >= POS_APP_LIST.y) && (item_rect_min <= MAX_LIST_POS);

// When the app is selected.
if (is_app_selected) {
if (is_current_app_selected) {
// Scroll to the app position when it is not visible.
if (item_rect_min < POS_APP_LIST.y)
ImGui::SetScrollHereY(0.f);
Expand Down Expand Up @@ -859,7 +877,7 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) {
}
} else if (!gui.is_nav_button && (current_selected_app_index == current_app_index)) {
// When the app is selected but not visible, reset the current selected app index.
current_selected_app_index = -5;
current_selected_app_index = INVALID_APP_INDEX;
}

if (!emuenv.cfg.apps_list_grid)
Expand Down Expand Up @@ -912,8 +930,6 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) {
ImGui::PopTextWrapPos();
}
ImGui::NextColumn();
if (selected)
pre_load_app(gui, emuenv, emuenv.cfg.show_live_area_screen, app.path);
ImGui::PopID();
}
};
Expand Down
88 changes: 56 additions & 32 deletions vita3k/gui/src/information_bar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,57 @@

namespace gui {

struct NoticeInfo {
struct NoticeList {
std::string id;
std::string content_id;
std::string group;
std::string type;
time_t time;
std::string name;
std::string msg;
bool is_new;
};

struct NoticeList {
std::string id;
std::string content_id;
std::string group;
std::string type;
time_t time;
struct NoticeInfo : NoticeList {
std::string name;
std::string msg;
};

static std::map<std::string, std::vector<NoticeList>> notice_list;
static std::map<std::string, int> notice_list_count_new;
static std::map<std::string, std::map<time_t, bool>> notice_list_new;
static std::map<time_t, bool> notice_info_new;
static int notice_info_count_new = 0;
static std::vector<NoticeInfo> notice_info;

void erase_app_notice(GuiState &gui, const std::string &title_id) {
auto &notice_global = notice_list["global"];

// Check if the notice list is empty
if (notice_global.empty()) {
LOG_WARN("Notice list is empty.");
return;
}

auto notice_list_it = notice_global.begin();
while (notice_list_it != notice_global.end()) {
if (notice_list_it->id == title_id) {
// Find and erase the corresponding entry in notice_info
const auto notice_info_it = std::find_if(notice_info.begin(), notice_info.end(), [&](const NoticeInfo &n) {
return n.time == notice_list_it->time;
});
if (notice_info_it != notice_info.end())
notice_info.erase(notice_info_it); // Erase the entry from notice_info

// Erase the entry from notice_info_icon if it exists
if (gui.notice_info_icon.contains(notice_list_it->time))
gui.notice_info_icon.erase(notice_list_it->time);

// Erase the item from notice_general and update the iterator
notice_list_it = notice_global.erase(notice_list_it);

LOG_INFO("Notice content with title id: {} has been erased.", title_id);
} else
++notice_list_it;
}
}

static bool init_notice_icon(GuiState &gui, EmuEnvState &emuenv, const fs::path &content_path, const NoticeList &info) {
gui.notice_info_icon[info.time] = {};
int32_t width = 0;
Expand Down Expand Up @@ -162,7 +188,7 @@ static bool set_notice_info(GuiState &gui, EmuEnvState &emuenv, const NoticeList
return false;
}

notice_info.push_back({ info.id, info.content_id, info.group, info.type, info.time, name, msg });
notice_info.push_back({ info, name, msg });

return true;
}
Expand All @@ -171,10 +197,7 @@ void init_notice_info(GuiState &gui, EmuEnvState &emuenv) {
if (!notice_info.empty()) {
notice_info.clear();
notice_info_count_new = 0;
for (auto &notice : gui.notice_info_icon)
notice.second = {};
gui.notice_info_icon.clear();
notice_info_new.clear();
}

if (!notice_list.empty()) {
Expand All @@ -185,10 +208,8 @@ void init_notice_info(GuiState &gui, EmuEnvState &emuenv) {
if (!set_notice_info(gui, emuenv, *notice_it)) {
notice_it = user.second.erase(notice_it);
save_notice_list(emuenv);
} else {
notice_info_new[notice_it->time] = notice_list_new[user.first][notice_it->time];
} else
++notice_it;
}
}
}
}
Expand All @@ -205,7 +226,6 @@ void init_notice_info(GuiState &gui, EmuEnvState &emuenv) {
void get_notice_list(EmuEnvState &emuenv) {
notice_list.clear();
notice_list_count_new.clear();
notice_list_new.clear();
const auto notice_path{ emuenv.pref_path / "ux0/user/notice.xml" };

if (fs::exists(notice_path)) {
Expand All @@ -224,7 +244,7 @@ void get_notice_list(EmuEnvState &emuenv) {
noticeList.group = notice.attribute("group").as_string();
noticeList.type = notice.attribute("type").as_string();
noticeList.time = !notice.attribute("time").empty() ? notice.attribute("time").as_llong() : (notice.attribute("date").as_llong() * 1000); // Backward Compat
notice_list_new[user_id][noticeList.time] = notice.attribute("new").as_bool();
noticeList.is_new = notice.attribute("new").as_bool();
notice_list[user_id].push_back(noticeList);
}
}
Expand Down Expand Up @@ -261,7 +281,7 @@ void save_notice_list(EmuEnvState &emuenv) {
info_child.append_attribute("group") = notice.group.c_str();
info_child.append_attribute("type") = notice.type.c_str();
info_child.append_attribute("time") = notice.time;
info_child.append_attribute("new") = notice_list_new[user.first][notice.time];
info_child.append_attribute("new") = notice.is_new;
}
}

Expand All @@ -286,12 +306,11 @@ void update_notice_info(GuiState &gui, EmuEnvState &emuenv, const std::string &t
}
info.type = type;
info.time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
notice_info_new[info.time] = true;
notice_list_new[user_id][info.time] = true;
info.is_new = true;
notice_list[user_id].push_back(info);
if (set_notice_info(gui, emuenv, info)) {
++notice_info_count_new;
++notice_list_count_new[user_id];
++notice_info_count_new;
std::sort(notice_info.begin(), notice_info.end(), [&](const NoticeInfo &na, const NoticeInfo &nb) {
return na.time > nb.time;
});
Expand All @@ -302,11 +321,16 @@ void update_notice_info(GuiState &gui, EmuEnvState &emuenv, const std::string &t

static void clean_notice_info_new(const std::string &user_id) {
notice_info_count_new = 0;
notice_info_new.clear();
notice_list_count_new["global"] = 0;
notice_list_count_new[user_id] = 0;
notice_list_new["global"].clear();
notice_list_new[user_id].clear();
for (auto &notice : notice_info)
notice.is_new = false;
for (auto &notice : notice_list) {
if ((notice.first == "global") || (notice.first == user_id)) {
for (auto &list : notice.second)
list.is_new = false;
}
}
}

static std::string get_notice_time(GuiState &gui, EmuEnvState &emuenv, const time_t &time) {
Expand Down Expand Up @@ -379,7 +403,7 @@ static void draw_notice_info(GuiState &gui, EmuEnvState &emuenv) {
}

if (ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow) && !ImGui::IsAnyItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
if (notice_info_state) {
if (notice_info_state && (notice_info_count_new > 0)) {
clean_notice_info_new(emuenv.io.user_id);
save_notice_list(emuenv);
}
Expand All @@ -395,6 +419,7 @@ static void draw_notice_info(GuiState &gui, EmuEnvState &emuenv) {
ImGui::PushStyleColor(ImGuiCol_Border, GUI_COLOR_TEXT);
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 10.f * SCALE.x);
ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, notice_info.empty() ? 0.f : 8.0f * SCALE.x);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.f, 0.f));
ImGui::SetNextWindowPos(POPUP_POS, ImGuiCond_Always);
ImGui::BeginChild("##notice_info_child", POPUP_SIZE, ImGuiChildFlags_Borders, ImGuiWindowFlags_NoSavedSettings);
auto &lang = gui.lang.indicator;
Expand Down Expand Up @@ -426,14 +451,14 @@ static void draw_notice_info(GuiState &gui, EmuEnvState &emuenv) {
ImGui::PushStyleColor(ImGuiCol_Header, SELECT_COLOR);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, SELECT_COLOR_HOVERED);
ImGui::PushStyleColor(ImGuiCol_HeaderActive, SELECT_COLOR_ACTIVE);
if (ImGui::Selectable("##icon", notice_info_new[notice.time], ImGuiSelectableFlags_SpanAllColumns, SELECT_SIZE)) {
if (ImGui::Selectable("##icon", notice.is_new, ImGuiSelectableFlags_SpanAllColumns, SELECT_SIZE)) {
clean_notice_info_new(emuenv.io.user_id);
save_notice_list(emuenv);
if (notice.type == "content") {
if (notice.group == "theme")
pre_load_app(gui, emuenv, false, "NPXS10015");
else
pre_load_app(gui, emuenv, emuenv.cfg.show_live_area_screen, notice.id);
select_app(gui, notice.id);
} else {
pre_load_app(gui, emuenv, false, "NPXS10008");
open_trophy_unlocked(gui, emuenv, notice.id, notice.content_id);
Expand All @@ -459,7 +484,7 @@ static void draw_notice_info(GuiState &gui, EmuEnvState &emuenv) {
}
ImGui::EndChild();
ImGui::PopStyleColor(2);
ImGui::PopStyleVar(2);
ImGui::PopStyleVar(3);

if (!notice_info.empty()) {
const auto DELETE_POPUP_SIZE = ImVec2(756.0f * SCALE.x, 436.0f * SCALE.y);
Expand Down Expand Up @@ -494,7 +519,6 @@ static void draw_notice_info(GuiState &gui, EmuEnvState &emuenv) {
gui.notice_info_icon.clear();
notice_list["global"].clear();
notice_list[emuenv.io.user_id].clear();
clean_notice_info_new(emuenv.io.user_id);
save_notice_list(emuenv);
notice_info_state = false;
ImGui::CloseCurrentPopup();
Expand Down
1 change: 1 addition & 0 deletions vita3k/gui/src/pkg_install_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ void draw_pkg_install_dialog(GuiState &gui, EmuEnvState &emuenv) {
if ((emuenv.app_info.app_category.find("gd") != std::string::npos) || (emuenv.app_info.app_category.find("gp") != std::string::npos)) {
init_user_app(gui, emuenv, emuenv.app_info.app_title_id);
save_apps_cache(gui, emuenv);
select_app(gui, emuenv.app_info.app_title_id);
}
update_notice_info(gui, emuenv, "content");
pkg_path = "";
Expand Down

0 comments on commit bfe9368

Please sign in to comment.