Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions components/kgui/kgui_ao.c
Original file line number Diff line number Diff line change
Expand Up @@ -15014,7 +15014,11 @@ static void gui_write_face_take(Gui * const me)
}

/**
* @brief A report of a write: keep, drop or take the face its card wears.
* @brief A report of a write: keep, drop or take the face its card wears, or
* ask its folder again.
*
* Asked again, the face stays on the card as it is: the folder's answer is
* written over it and drawn when it has all arrived (gui_write_face_settle()).
*
* @param me The AO.
* @param p The report.
Expand All @@ -15028,11 +15032,20 @@ static void gui_write_face_report(Gui * const me, const AppProgressEvt *p)
if ( KGUI_WFACE_TAKE == act )
{
gui_write_face_take(me);
gui_write_face_show(me);
}
if ( KGUI_WFACE_KEEP != act )
else if ( KGUI_WFACE_DROP == act )
{
gui_write_face_show(me);
}
else if ( KGUI_WFACE_AGAIN == act )
{
gui_ask_next_appdata(me);
}
else
{
/* The same app, or still nobody. */
}
}

/**
Expand Down
20 changes: 17 additions & 3 deletions components/kgui/kgui_wface.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,36 @@ kgui_wface_act_t kgui_wface_report(kgui_wface_t *w, bool app, const char *projec
{
kgui_wface_act_t act = KGUI_WFACE_KEEP;

if ( !app || ('\0' == project[0]) )
if ( !app )
{
if ( kgui_wface_has(w) )
{
kgui_wface_end(w);
act = KGUI_WFACE_DROP;
}
}
else if ( '\0' == project[0] )
{
/* The next transfer on the card, its image still unread: the face
* stays, and its folder is asked again, once for the stretch. */
if ( kgui_wface_has(w) && !w->unnamed )
{
w->unnamed = true;
w->owed = true;
act = KGUI_WFACE_AGAIN;
}
}
else if ( strncmp(w->project, project, sizeof(w->project) - 1U) != 0 )
{
(void)snprintf(w->project, sizeof(w->project), "%s", project);
w->owed = true;
act = KGUI_WFACE_TAKE;
w->owed = true;
w->unnamed = false;
act = KGUI_WFACE_TAKE;
}
else
{
/* The app the card already wears. */
w->unnamed = false;
}
return act;
}
Expand All @@ -37,6 +50,7 @@ void kgui_wface_end(kgui_wface_t *w)
{
w->project[0] = '\0';
w->owed = false;
w->unnamed = false;
}

bool kgui_wface_has(const kgui_wface_t *w)
Expand Down
19 changes: 15 additions & 4 deletions components/kgui/kgui_wface.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@
* is named for its project and may be on the board before the app is: the
* card wears that folder's name, icon and colour. This is the part that
* decides, from each report, whether the card keeps the face it has, drops
* it, or takes a new one; the face itself and its folder's question are the
* launcher's.
* it, takes a new one, or asks the folder behind it again; the face itself and
* its folder's question are the launcher's.
*
* A card can carry more than one transfer: the fetch of an app's data folder
* and the install it announced, or an install that starts again once its
* copies are on the card. The reports of the later one name no project until
* its image is read. The card keeps its face through them, and the folder is
* asked again, once: the transfer before may be the one that wrote it.
*/
#ifndef KGUI_WFACE_H
#define KGUI_WFACE_H
Expand All @@ -28,13 +34,16 @@ extern "C" {
typedef enum {
KGUI_WFACE_KEEP = 0, /**< Nothing: the same app, or still nobody. */
KGUI_WFACE_DROP, /**< The card is about no app any more: the face goes. */
KGUI_WFACE_TAKE /**< Another app: its face is to be taken. */
KGUI_WFACE_TAKE, /**< Another app: its face is to be taken. */
KGUI_WFACE_AGAIN /**< The same face: its folder is to be asked again. */
} kgui_wface_act_t;

/** @brief Whose face the card wears. */
typedef struct {
char project[KGUI_WFACE_PROJECT_MAX]; /**< The app's project name; "" for nobody. */
bool owed; /**< Its folder is still to be asked. */
bool unnamed; /**< The last report named nobody, and the
* folder was asked again for it. */
} kgui_wface_t;

/**
Expand All @@ -45,7 +54,9 @@ typedef struct {
* @param project The project the report names; "" when it names none.
* @return KGUI_WFACE_TAKE for an app other than the one the card wears, with
* @c owed set; KGUI_WFACE_DROP when the card wore a face and the
* report is no app's or names none; KGUI_WFACE_KEEP otherwise.
* report is no app's; KGUI_WFACE_AGAIN, with @c owed set, for the first
* of an app's reports that name nobody on a card that wears a face;
* KGUI_WFACE_KEEP otherwise.
*/
kgui_wface_act_t kgui_wface_report(kgui_wface_t *w, bool app, const char *project);

Expand Down
72 changes: 68 additions & 4 deletions components/kgui/test/test_kgui_wface.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,74 @@ void test_a_write_that_is_no_app_drops_the_face(void)
TEST_ASSERT_EQUAL_INT(KGUI_WFACE_KEEP, kgui_wface_report(&w, false, ""));
}

void test_an_app_report_with_no_name_drops_a_face_of_another_write(void)
void test_an_app_report_with_no_name_keeps_the_face_and_asks_its_folder_again(void)
{
kgui_wface_t w = { 0 };

(void)kgui_wface_report(&w, true, "snake");
/* A write whose project is not known yet: it is not the one before. */
TEST_ASSERT_EQUAL_INT(KGUI_WFACE_DROP, kgui_wface_report(&w, true, ""));
w.owed = false; /* its folder was asked */
/* The next transfer on the card, its image still unread: the install a
* fetch announced, or an install that starts again after its copies. */
TEST_ASSERT_EQUAL_INT(KGUI_WFACE_AGAIN, kgui_wface_report(&w, true, ""));
TEST_ASSERT_TRUE_MESSAGE(kgui_wface_is(&w, "snake"),
"the card lost its face between a fetch and the install it announced");
TEST_ASSERT_TRUE_MESSAGE(w.owed,
"the folder the transfer before may have written was not asked again");
}

void test_a_nameless_stretch_asks_the_folder_once(void)
{
kgui_wface_t w = { 0 };

(void)kgui_wface_report(&w, true, "snake");
(void)kgui_wface_report(&w, true, "");
w.owed = false; /* asked again */
/* The same report every second while a download opens. */
TEST_ASSERT_EQUAL_INT(KGUI_WFACE_KEEP, kgui_wface_report(&w, true, ""));
TEST_ASSERT_EQUAL_INT(KGUI_WFACE_KEEP, kgui_wface_report(&w, true, ""));
TEST_ASSERT_FALSE_MESSAGE(w.owed, "every second would ask the folder again");
TEST_ASSERT_TRUE(kgui_wface_is(&w, "snake"));
}

void test_the_image_naming_the_same_app_changes_nothing(void)
{
kgui_wface_t w = { 0 };

(void)kgui_wface_report(&w, true, "snake");
(void)kgui_wface_report(&w, true, "");
w.owed = false;
/* The first chunk is read and names the app the card already wears. */
TEST_ASSERT_EQUAL_INT(KGUI_WFACE_KEEP, kgui_wface_report(&w, true, "snake"));
TEST_ASSERT_FALSE(w.owed);
/* A second nameless stretch (the install starts again) asks once more. */
TEST_ASSERT_EQUAL_INT(KGUI_WFACE_AGAIN, kgui_wface_report(&w, true, ""));
TEST_ASSERT_TRUE(w.owed);
}

void test_the_image_naming_another_app_takes_its_face(void)
{
kgui_wface_t w = { 0 };

(void)kgui_wface_report(&w, true, "ladder"); /* what the fetch was for */
(void)kgui_wface_report(&w, true, "");
w.owed = false;
TEST_ASSERT_EQUAL_INT(KGUI_WFACE_TAKE, kgui_wface_report(&w, true, "snake"));
TEST_ASSERT_TRUE(kgui_wface_is(&w, "snake"));
TEST_ASSERT_TRUE(w.owed);
}

void test_a_write_that_is_no_app_drops_a_face_kept_through_a_nameless_stretch(void)
{
kgui_wface_t w = { 0 };

(void)kgui_wface_report(&w, true, "snake");
(void)kgui_wface_report(&w, true, "");
TEST_ASSERT_EQUAL_INT(KGUI_WFACE_DROP, kgui_wface_report(&w, false, ""));
TEST_ASSERT_FALSE(kgui_wface_has(&w));
TEST_ASSERT_FALSE(w.owed);
/* And the next card starts clean: a nameless report asks nothing. */
TEST_ASSERT_EQUAL_INT(KGUI_WFACE_KEEP, kgui_wface_report(&w, true, ""));
TEST_ASSERT_FALSE(w.owed);
}

void test_the_end_of_a_write_forgets_the_face(void)
Expand Down Expand Up @@ -119,7 +179,11 @@ int main(void)
RUN_TEST(test_a_report_that_names_nobody_keeps_a_card_with_no_face);
RUN_TEST(test_another_app_takes_the_face_over);
RUN_TEST(test_a_write_that_is_no_app_drops_the_face);
RUN_TEST(test_an_app_report_with_no_name_drops_a_face_of_another_write);
RUN_TEST(test_an_app_report_with_no_name_keeps_the_face_and_asks_its_folder_again);
RUN_TEST(test_a_nameless_stretch_asks_the_folder_once);
RUN_TEST(test_the_image_naming_the_same_app_changes_nothing);
RUN_TEST(test_the_image_naming_another_app_takes_its_face);
RUN_TEST(test_a_write_that_is_no_app_drops_a_face_kept_through_a_nameless_stretch);
RUN_TEST(test_the_end_of_a_write_forgets_the_face);
RUN_TEST(test_an_answer_is_the_cards_only_by_its_project);
RUN_TEST(test_a_name_longer_than_a_project_is_cut_not_overrun);
Expand Down
Loading