/* * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "wakeup_ui.h" #include "applib/fonts/fonts.h" #include "applib/ui/dialogs/expandable_dialog.h" #include "applib/ui/ui.h" #include "applib/ui/window.h" #include "kernel/event_loop.h" #include "kernel/pbl_malloc.h" #include "kernel/ui/kernel_ui.h" #include "kernel/ui/modals/modal_manager.h" #include "process_management/app_install_manager.h" #include "process_state/app_state/app_state.h" #include "resource/resource_ids.auto.h" #include "services/common/i18n/i18n.h" typedef void (*EachCb)(AppInstallEntry *entry, void *data); void prv_find_len_helper(AppInstallEntry *entry, void *context) { uint32_t *len = context; *len += strlen(entry->name) + 1; } void prv_string_builder(AppInstallEntry *entry, void *context) { char *str = context; strcat(str, entry->name); strcat(str, "\n"); } void prv_each_app_ids(uint32_t num_ids, AppInstallId *ids, EachCb cb, void *context) { for (uint32_t i = 0; i < num_ids; i++) { // app_title +1 to add newline per line AppInstallId app_id = ids[i]; AppInstallEntry entry; if (!app_install_get_entry_for_install_id(app_id, &entry)) { continue; } cb(&entry, context); } } typedef struct { uint8_t count; AppInstallId *app_ids; } WakeupUICbData; static void prv_show_dialog(void *context) { WakeupUICbData *data = context; const char* missed_text_raw = i18n_noop("While your Pebble was off wakeup events occurred for:\n"); const char* missed_text = i18n_get(missed_text_raw, data); // Find the size of all of the missed_apps names (no max length defined) int16_t missed_app_titles_len = 0; prv_each_app_ids(data->count, data->app_ids, prv_find_len_helper, &missed_app_titles_len); int16_t missed_message_len = strlen(missed_text) + missed_app_titles_len; char *missed_message = kernel_zalloc(missed_message_len + 1); strncpy(missed_message, missed_text, strlen(missed_text)); i18n_free(missed_text, data); prv_each_app_ids(data->count, data->app_ids, prv_string_builder, missed_message); missed_message[missed_message_len] = '\0'; // must free the buffer passed in kernel_free(data->app_ids); kernel_free(data); ExpandableDialog * ex_dialog = expandable_dialog_create(NULL); Dialog *dialog = expandable_dialog_get_dialog(ex_dialog); dialog_set_text_buffer(dialog, missed_message, true); dialog_set_icon(dialog, RESOURCE_ID_GENERIC_WARNING_TINY); dialog_show_status_bar_layer(dialog, true); expandable_dialog_push(ex_dialog, modal_manager_get_window_stack(ModalPriorityGeneric)); } // --------------------------------------------------------------------------- // Display our alert void wakeup_popup_window(uint8_t missed_apps_count, AppInstallId *missed_app_ids) { WakeupUICbData *data = kernel_malloc(sizeof(WakeupUICbData)); if (data) { *data = (WakeupUICbData) { .count = missed_apps_count, .app_ids = missed_app_ids, }; launcher_task_add_callback(prv_show_dialog, data); } // don't really care if it fails. }