~aleteoryx/muditaos

1b37e62f421da928fbdb367f49116e05f680e5e4 — Lefucjusz 1 year, 9 months ago cdf5dbf
[MOS-1067] Fix Pure crash when deleting all contacts

Fix of the issue that Pure would crash
when trying to delete all contacts from
Mudita Center when main window of
phonebook was opened and focus was
set on different contact than the
first one in the list.
M module-apps/application-phonebook/windows/PhonebookMainWindow.cpp => module-apps/application-phonebook/windows/PhonebookMainWindow.cpp +9 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PhonebookMainWindow.hpp"


@@ 166,7 166,14 @@ namespace gui
        if ((msgNotification != nullptr) && (msgNotification->interface == db::Interface::Name::Contact) &&
            msgNotification->dataModified()) {
            phonebookModel->letterMap = phonebookModel->requestLetterMap();
            rebuild();
            if (msgNotification->type == db::Query::Type::Delete) {
                /* Perform full rebuild to prevent crash in case current
                 * list index > number of remaining elements. */
                contactsList->rebuildList(gui::listview::RebuildType::Full);
            }
            else {
                contactsList->rebuildList(gui::listview::RebuildType::InPlace);
            }
            return true;
        }
        return false;

M module-db/Tables/ContactsTable.cpp => module-db/Tables/ContactsTable.cpp +27 -27
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ContactsTable.hpp"


@@ 8,24 8,24 @@

namespace ColumnName
{
    const uint8_t id         = 0;
    const uint8_t name_id    = 1;
    const uint8_t numbers_id = 2;
    const uint8_t ring_id    = 3;
    const uint8_t address_id = 4;
    const uint8_t speeddial  = 5;
    constexpr std::uint8_t id         = 0;
    constexpr std::uint8_t name_id    = 1;
    constexpr std::uint8_t numbers_id = 2;
    constexpr std::uint8_t ring_id    = 3;
    constexpr std::uint8_t address_id = 4;
    constexpr std::uint8_t speeddial  = 5;
}; // namespace ColumnName

namespace statements
{
    const auto selectWithoutTemp = "SELECT * FROM contacts WHERE _id=" u32_ " AND "
                                   " contacts._id NOT IN ( "
                                   "   SELECT cmg.contact_id "
                                   "   FROM contact_match_groups cmg, contact_groups cg "
                                   "   WHERE cmg.group_id = cg._id "
                                   "       AND cg.name = 'Temporary' "
                                   "   ) ";
    const auto selectWithTemp = "SELECT * FROM contacts WHERE _id=" u32_ ";";
    constexpr auto selectWithoutTemp = "SELECT * FROM contacts WHERE _id=" u32_ " AND "
                                       " contacts._id NOT IN ( "
                                       "   SELECT cmg.contact_id "
                                       "   FROM contact_match_groups cmg, contact_groups cg "
                                       "   WHERE cmg.group_id = cg._id "
                                       "       AND cg.name = 'Temporary' "
                                       "   ) ";
    constexpr auto selectWithTemp = "SELECT * FROM contacts WHERE _id=" u32_ ";";
} // namespace statements

ContactsTable::ContactsTable(Database *db) : Table(db)


@@ 50,12 50,12 @@ bool ContactsTable::add(ContactsTableRow entry)
                       entry.speedDial.c_str());
}

bool ContactsTable::removeById(uint32_t id)
bool ContactsTable::removeById(std::uint32_t id)
{
    return db->execute("DELETE FROM contacts where _id=" u32_ ";", id);
}

bool ContactsTable::BlockByID(uint32_t id, bool shouldBeBlocked)
bool ContactsTable::BlockByID(std::uint32_t id, bool shouldBeBlocked)
{
    return db->execute("UPDATE contacts SET blacklist=" u32_ " WHERE _id=" u32_ ";", shouldBeBlocked ? 1 : 0, id);
}


@@ 72,13 72,13 @@ bool ContactsTable::update(ContactsTableRow entry)
                       entry.ID);
}

ContactsTableRow ContactsTable::getById(uint32_t id)
ContactsTableRow ContactsTable::getById(std::uint32_t id)
{
    auto retQuery = db->query(statements::selectWithoutTemp, id);
    return getByIdCommon(std::move(retQuery));
}

ContactsTableRow ContactsTable::getByIdWithTemporary(uint32_t id)
ContactsTableRow ContactsTable::getByIdWithTemporary(std::uint32_t id)
{
    debug_db_data("%s", __FUNCTION__);
    auto retQuery = db->query(statements::selectWithTemp, id);


@@ 218,7 218,7 @@ std::vector<std::uint32_t> ContactsTable::GetIDsSortedByName(std::uint32_t limit
        } while (queryRet->nextRow());

    if (limit > 0) {
        for (uint32_t a = 0; a < limit; a++) {
        for (std::uint32_t a = 0; a < limit; a++) {
            ids_limit.push_back(ids[a + offset]);
        }
        return ids_limit;


@@ 354,7 354,7 @@ std::vector<std::uint32_t> ContactsTable::GetIDsSortedByField(
    return ids;
}

std::vector<ContactsTableRow> ContactsTable::getLimitOffset(uint32_t offset, uint32_t limit)
std::vector<ContactsTableRow> ContactsTable::getLimitOffset(std::uint32_t offset, std::uint32_t limit)
{
    auto retQuery = db->query("SELECT * from contacts WHERE contacts._id NOT IN "
                              " ( SELECT cmg.contact_id "


@@ 386,8 386,8 @@ std::vector<ContactsTableRow> ContactsTable::getLimitOffset(uint32_t offset, uin
    return ret;
}

std::vector<ContactsTableRow> ContactsTable::getLimitOffsetByField(uint32_t offset,
                                                                   uint32_t limit,
std::vector<ContactsTableRow> ContactsTable::getLimitOffsetByField(std::uint32_t offset,
                                                                   std::uint32_t limit,
                                                                   ContactTableFields field,
                                                                   const char *str)
{


@@ 428,7 428,7 @@ std::vector<ContactsTableRow> ContactsTable::getLimitOffsetByField(uint32_t offs
    return ret;
}

uint32_t ContactsTable::count()
std::uint32_t ContactsTable::count()
{
    auto queryRet = db->query("SELECT COUNT(*) FROM contacts "
                              " WHERE contacts._id not in ( "


@@ 442,10 442,10 @@ uint32_t ContactsTable::count()
        return 0;
    }

    return uint32_t{(*queryRet)[0].getUInt32()};
    return (*queryRet)[0].getUInt32();
}

uint32_t ContactsTable::countByFieldId(const char *field, uint32_t id)
std::uint32_t ContactsTable::countByFieldId(const char *field, std::uint32_t id)
{
    auto queryRet = db->query("SELECT COUNT(*) FROM contacts WHERE %q=" u32_ ";", field, id);



@@ 453,5 453,5 @@ uint32_t ContactsTable::countByFieldId(const char *field, uint32_t id)
        return 0;
    }

    return uint32_t{(*queryRet)[0].getUInt32()};
    return (*queryRet)[0].getUInt32();
}

M module-db/Tables/ContactsTable.hpp => module-db/Tables/ContactsTable.hpp +14 -25
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 16,10 16,10 @@

struct ContactsTableRow : public Record
{
    uint32_t nameID       = DB_ID_NONE;
    std::uint32_t nameID    = DB_ID_NONE;
    std::string numbersID = "";
    uint32_t ringID       = DB_ID_NONE;
    uint32_t addressID    = DB_ID_NONE;
    std::uint32_t ringID    = DB_ID_NONE;
    std::uint32_t addressID = DB_ID_NONE;
    std::string speedDial = "";
    UTF8 namePrimary      = "";
    UTF8 nameAlternative  = "";


@@ 27,7 27,7 @@ struct ContactsTableRow : public Record

enum class ContactTableFields
{
    SpeedDial,
    SpeedDial
};

class ContactsTable : public Table<ContactsTableRow, ContactTableFields>


@@ 38,44 38,33 @@ class ContactsTable : public Table<ContactsTableRow, ContactTableFields>
        Name,
        TextNumber,
        Group,

        None,
        None
    };

    ContactsTable(Database *db);

    virtual ~ContactsTable();

    bool create() override final;

    bool add(ContactsTableRow entry) override final;

    bool removeById(uint32_t id) override final;

    bool removeById(std::uint32_t id) override final;
    bool update(ContactsTableRow entry) override final;

    ContactsTableRow getById(uint32_t id) override final;
    ContactsTableRow getByIdWithTemporary(uint32_t id);
    ContactsTableRow getById(std::uint32_t id) override final;
    ContactsTableRow getByIdWithTemporary(std::uint32_t id);

  private:
    ContactsTableRow getByIdCommon(std::unique_ptr<QueryResult> retQuery);

  public:
    bool BlockByID(uint32_t id, bool shouldBeBlocked);
    bool BlockByID(std::uint32_t id, bool shouldBeBlocked);

    std::vector<ContactsTableRow> Search(const std::string &primaryName,
                                         const std::string &alternativeName,
                                         const std::string &number);

    std::vector<ContactsTableRow> getLimitOffset(uint32_t offset, uint32_t limit) override final;

    std::vector<ContactsTableRow> getLimitOffsetByField(uint32_t offset,
                                                        uint32_t limit,
    std::vector<ContactsTableRow> getLimitOffset(std::uint32_t offset, std::uint32_t limit) override final;
    std::vector<ContactsTableRow> getLimitOffsetByField(std::uint32_t offset,
                                                        std::uint32_t limit,
                                                        ContactTableFields field,
                                                        const char *str) override final;

    uint32_t count() override final;

    uint32_t countByFieldId(const char *field, uint32_t id) override final;

    std::vector<std::uint32_t> GetIDsSortedByField(MatchType matchType,


@@ 83,11 72,11 @@ class ContactsTable : public Table<ContactsTableRow, ContactTableFields>
                                                   std::uint32_t groupId,
                                                   std::uint32_t limit  = 0,
                                                   std::uint32_t offset = 0);

    std::vector<std::uint32_t> GetIDsSortedByName(std::uint32_t limit = 0, std::uint32_t offset = 0);

    ContactsMapData GetPosOfFirstLetters();
    std::string GetSortedByNameQueryString(ContactQuerySection section);

  private:
    ContactsTableRow getByIdCommon(std::unique_ptr<QueryResult> retQuery);
};

M pure_changelog.md => pure_changelog.md +1 -0
@@ 6,6 6,7 @@
* Fixed no response when editing a contact via Center to have the same number as another.
* Fixed occasional screen backlight flash when turning off the phone.
* Fixed device freeze after finishing onboarding in Spanish.
* Fixed crash when deleting all contacts from MC with Phonebook app opened.

### Added