Updater visual fixes (#2391)
* updater: removed unused code; fbt: fixed build error processing in certain cases * updater: simplified internal pre-update state * updater: rebalanced stage weights; fixed progress hiccups
This commit is contained in:
		@@ -58,8 +58,12 @@ bool updater_scene_error_on_event(void* context, SceneManagerEvent event) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void updater_scene_error_on_exit(void* context) {
 | 
			
		||||
    furi_assert(context);
 | 
			
		||||
    Updater* updater = (Updater*)context;
 | 
			
		||||
 | 
			
		||||
    widget_reset(updater->widget);
 | 
			
		||||
    free(updater->pending_update);
 | 
			
		||||
 | 
			
		||||
    if(updater->loaded_manifest) {
 | 
			
		||||
        update_manifest_free(updater->loaded_manifest);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,11 +21,9 @@ void updater_scene_loadcfg_apply_callback(GuiButtonType result, InputType type,
 | 
			
		||||
 | 
			
		||||
void updater_scene_loadcfg_on_enter(void* context) {
 | 
			
		||||
    Updater* updater = (Updater*)context;
 | 
			
		||||
    UpdaterManifestProcessingState* pending_upd = updater->pending_update =
 | 
			
		||||
        malloc(sizeof(UpdaterManifestProcessingState));
 | 
			
		||||
    pending_upd->manifest = update_manifest_alloc();
 | 
			
		||||
    UpdateManifest* loaded_manifest = updater->loaded_manifest = update_manifest_alloc();
 | 
			
		||||
 | 
			
		||||
    if(update_manifest_init(pending_upd->manifest, furi_string_get_cstr(updater->startup_arg))) {
 | 
			
		||||
    if(update_manifest_init(loaded_manifest, furi_string_get_cstr(updater->startup_arg))) {
 | 
			
		||||
        widget_add_string_element(
 | 
			
		||||
            updater->widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, "Update");
 | 
			
		||||
 | 
			
		||||
@@ -37,7 +35,7 @@ void updater_scene_loadcfg_on_enter(void* context) {
 | 
			
		||||
            32,
 | 
			
		||||
            AlignCenter,
 | 
			
		||||
            AlignCenter,
 | 
			
		||||
            furi_string_get_cstr(pending_upd->manifest->version),
 | 
			
		||||
            furi_string_get_cstr(loaded_manifest->version),
 | 
			
		||||
            true);
 | 
			
		||||
 | 
			
		||||
        widget_add_button_element(
 | 
			
		||||
@@ -95,13 +93,12 @@ bool updater_scene_loadcfg_on_event(void* context, SceneManagerEvent event) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void updater_scene_loadcfg_on_exit(void* context) {
 | 
			
		||||
    furi_assert(context);
 | 
			
		||||
    Updater* updater = (Updater*)context;
 | 
			
		||||
 | 
			
		||||
    if(updater->pending_update) {
 | 
			
		||||
        update_manifest_free(updater->pending_update->manifest);
 | 
			
		||||
        furi_string_free(updater->pending_update->message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    widget_reset(updater->widget);
 | 
			
		||||
    free(updater->pending_update);
 | 
			
		||||
 | 
			
		||||
    if(updater->loaded_manifest) {
 | 
			
		||||
        update_manifest_free(updater->loaded_manifest);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,12 +33,6 @@ typedef enum {
 | 
			
		||||
    UpdaterCustomEventSdUnmounted,
 | 
			
		||||
} UpdaterCustomEvent;
 | 
			
		||||
 | 
			
		||||
typedef struct UpdaterManifestProcessingState {
 | 
			
		||||
    UpdateManifest* manifest;
 | 
			
		||||
    FuriString* message;
 | 
			
		||||
    bool ready_to_be_applied;
 | 
			
		||||
} UpdaterManifestProcessingState;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    // GUI
 | 
			
		||||
    Gui* gui;
 | 
			
		||||
@@ -49,7 +43,7 @@ typedef struct {
 | 
			
		||||
 | 
			
		||||
    UpdaterMainView* main_view;
 | 
			
		||||
 | 
			
		||||
    UpdaterManifestProcessingState* pending_update;
 | 
			
		||||
    UpdateManifest* loaded_manifest;
 | 
			
		||||
    UpdatePrepareResult preparation_result;
 | 
			
		||||
 | 
			
		||||
    UpdateTask* update_task;
 | 
			
		||||
 
 | 
			
		||||
@@ -41,22 +41,22 @@ typedef struct {
 | 
			
		||||
static const UpdateTaskStageGroupMap update_task_stage_progress[] = {
 | 
			
		||||
    [UpdateTaskStageProgress] = STAGE_DEF(UpdateTaskStageGroupMisc, 0),
 | 
			
		||||
 | 
			
		||||
    [UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5),
 | 
			
		||||
    [UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 15),
 | 
			
		||||
    [UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 45),
 | 
			
		||||
    [UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5),
 | 
			
		||||
 | 
			
		||||
    [UpdateTaskStageRadioImageValidate] = STAGE_DEF(UpdateTaskStageGroupRadio, 15),
 | 
			
		||||
    [UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 60),
 | 
			
		||||
    [UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 80),
 | 
			
		||||
    [UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 60),
 | 
			
		||||
    [UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 80),
 | 
			
		||||
    [UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 35),
 | 
			
		||||
    [UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 60),
 | 
			
		||||
    [UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 30),
 | 
			
		||||
    [UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 5),
 | 
			
		||||
 | 
			
		||||
    [UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 10),
 | 
			
		||||
    [UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 2),
 | 
			
		||||
 | 
			
		||||
    [UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 50),
 | 
			
		||||
    [UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 200),
 | 
			
		||||
    [UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 30),
 | 
			
		||||
    [UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 30),
 | 
			
		||||
    [UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 150),
 | 
			
		||||
    [UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 15),
 | 
			
		||||
 | 
			
		||||
    [UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 30),
 | 
			
		||||
    [UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 5),
 | 
			
		||||
 | 
			
		||||
    [UpdateTaskStageResourcesUpdate] = STAGE_DEF(UpdateTaskStageGroupResources, 255),
 | 
			
		||||
    [UpdateTaskStageSplashscreenInstall] = STAGE_DEF(UpdateTaskStageGroupSplashscreen, 5),
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,14 @@ static bool update_task_pre_update(UpdateTask* update_task) {
 | 
			
		||||
    return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    UpdateTaskResourcesWeightsFileCleanup = 20,
 | 
			
		||||
    UpdateTaskResourcesWeightsDirCleanup = 20,
 | 
			
		||||
    UpdateTaskResourcesWeightsFileUnpack = 60,
 | 
			
		||||
} UpdateTaskResourcesWeights;
 | 
			
		||||
 | 
			
		||||
#define UPDATE_TASK_RESOURCES_FILE_TO_TOTAL_PERCENT 90
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    UpdateTask* update_task;
 | 
			
		||||
    int32_t total_files, processed_files;
 | 
			
		||||
@@ -54,33 +62,36 @@ static bool update_task_resource_unpack_cb(const char* name, bool is_directory,
 | 
			
		||||
    update_task_set_progress(
 | 
			
		||||
        unpack_progress->update_task,
 | 
			
		||||
        UpdateTaskStageProgress,
 | 
			
		||||
        /* For this stage, last 70% of progress = extraction */
 | 
			
		||||
        30 + (unpack_progress->processed_files * 70) / (unpack_progress->total_files + 1));
 | 
			
		||||
        /* For this stage, last progress segment = extraction */
 | 
			
		||||
        (UpdateTaskResourcesWeightsFileCleanup + UpdateTaskResourcesWeightsDirCleanup) +
 | 
			
		||||
            (unpack_progress->processed_files * UpdateTaskResourcesWeightsFileUnpack) /
 | 
			
		||||
                (unpack_progress->total_files + 1));
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
    update_task_cleanup_resources(UpdateTask* update_task, uint32_t n_approx_file_entries) {
 | 
			
		||||
static void update_task_cleanup_resources(UpdateTask* update_task, const uint32_t n_tar_entries) {
 | 
			
		||||
    ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(update_task->storage);
 | 
			
		||||
    do {
 | 
			
		||||
        FURI_LOG_I(TAG, "Cleaning up old manifest");
 | 
			
		||||
        FURI_LOG_D(TAG, "Cleaning up old manifest");
 | 
			
		||||
        if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("Manifest"))) {
 | 
			
		||||
            FURI_LOG_W(TAG, "No existing manifest");
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* We got # of entries in TAR file. Approx 1/4th is dir entries, we skip them */
 | 
			
		||||
        n_approx_file_entries = n_approx_file_entries * 3 / 4 + 1;
 | 
			
		||||
        uint32_t n_processed_files = 0;
 | 
			
		||||
        const uint32_t n_approx_file_entries =
 | 
			
		||||
            n_tar_entries * UPDATE_TASK_RESOURCES_FILE_TO_TOTAL_PERCENT / 100 + 1;
 | 
			
		||||
        uint32_t n_dir_entries = 1;
 | 
			
		||||
 | 
			
		||||
        ResourceManifestEntry* entry_ptr = NULL;
 | 
			
		||||
        uint32_t n_processed_entries = 0;
 | 
			
		||||
        while((entry_ptr = resource_manifest_reader_next(manifest_reader))) {
 | 
			
		||||
            if(entry_ptr->type == ResourceManifestEntryTypeFile) {
 | 
			
		||||
                update_task_set_progress(
 | 
			
		||||
                    update_task,
 | 
			
		||||
                    UpdateTaskStageProgress,
 | 
			
		||||
                    /* For this stage, first 20% of progress = cleanup files */
 | 
			
		||||
                    (n_processed_files++ * 20) / (n_approx_file_entries + 1));
 | 
			
		||||
                    /* For this stage, first pass = old manifest's file cleanup */
 | 
			
		||||
                    (n_processed_entries++ * UpdateTaskResourcesWeightsFileCleanup) /
 | 
			
		||||
                        n_approx_file_entries);
 | 
			
		||||
 | 
			
		||||
                FuriString* file_path = furi_string_alloc();
 | 
			
		||||
                path_concat(
 | 
			
		||||
@@ -88,16 +99,21 @@ static void
 | 
			
		||||
                FURI_LOG_D(TAG, "Removing %s", furi_string_get_cstr(file_path));
 | 
			
		||||
                storage_simply_remove(update_task->storage, furi_string_get_cstr(file_path));
 | 
			
		||||
                furi_string_free(file_path);
 | 
			
		||||
            } else if(entry_ptr->type == ResourceManifestEntryTypeDirectory) {
 | 
			
		||||
                n_dir_entries++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        n_processed_entries = 0;
 | 
			
		||||
        while((entry_ptr = resource_manifest_reader_previous(manifest_reader))) {
 | 
			
		||||
            if(entry_ptr->type == ResourceManifestEntryTypeDirectory) {
 | 
			
		||||
                update_task_set_progress(
 | 
			
		||||
                    update_task,
 | 
			
		||||
                    UpdateTaskStageProgress,
 | 
			
		||||
                    /* For this stage, second 10% of progress = cleanup directories */
 | 
			
		||||
                    (n_processed_files++ * 10) / (n_approx_file_entries + 1));
 | 
			
		||||
                    UpdateTaskResourcesWeightsFileCleanup +
 | 
			
		||||
                        (n_processed_entries++ * UpdateTaskResourcesWeightsDirCleanup) /
 | 
			
		||||
                            n_dir_entries);
 | 
			
		||||
 | 
			
		||||
                FuriString* folder_path = furi_string_alloc();
 | 
			
		||||
                File* folder_file = storage_file_alloc(update_task->storage);
 | 
			
		||||
 
 | 
			
		||||
@@ -106,6 +106,7 @@ void tar_archive_set_file_callback(TarArchive* archive, tar_unpack_file_cb callb
 | 
			
		||||
static int tar_archive_entry_counter(mtar_t* tar, const mtar_header_t* header, void* param) {
 | 
			
		||||
    UNUSED(tar);
 | 
			
		||||
    UNUSED(header);
 | 
			
		||||
    furi_assert(param);
 | 
			
		||||
    int32_t* counter = param;
 | 
			
		||||
    (*counter)++;
 | 
			
		||||
    return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
from SCons.Builder import Builder
 | 
			
		||||
from SCons.Action import Action
 | 
			
		||||
from SCons.Script import Delete, Mkdir, GetBuildFailures
 | 
			
		||||
from SCons.Script import Delete, Mkdir, GetBuildFailures, Flatten
 | 
			
		||||
import multiprocessing
 | 
			
		||||
import webbrowser
 | 
			
		||||
import atexit
 | 
			
		||||
@@ -30,13 +30,14 @@ def atexist_handler():
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    for bf in GetBuildFailures():
 | 
			
		||||
        if bf.node.exists and bf.node.name.endswith(".html"):
 | 
			
		||||
            # macOS
 | 
			
		||||
            if sys.platform == "darwin":
 | 
			
		||||
                subprocess.run(["open", bf.node.abspath])
 | 
			
		||||
            else:
 | 
			
		||||
                webbrowser.open(bf.node.abspath)
 | 
			
		||||
            break
 | 
			
		||||
        for node in Flatten(bf.node):
 | 
			
		||||
            if node.exists and node.name.endswith(".html"):
 | 
			
		||||
                # macOS
 | 
			
		||||
                if sys.platform == "darwin":
 | 
			
		||||
                    subprocess.run(["open", node.abspath])
 | 
			
		||||
                else:
 | 
			
		||||
                    webbrowser.open(node.abspath)
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def generate(env):
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user