// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once #include #include #include #include #include #include "Record.hpp" #include "utf8/UTF8.hpp" #include #include #include "module-gui/gui/widgets/TextConstants.hpp" #include #include #include #include #include struct ContactRecord : public Record { UTF8 primaryName = ""; UTF8 alternativeName = ""; uint32_t contactPosOnList = 0; struct Number { utils::PhoneNumber::View number; ContactNumberType numberType = ContactNumberType::OTHER; Number(); explicit Number(const utils::PhoneNumber::View &number, ContactNumberType = ContactNumberType::CELL); explicit Number(const std::string &entered, const std::string &e164, ContactNumberType n_type = ContactNumberType::CELL); }; std::vector numbers = {}; UTF8 address = ""; UTF8 note = ""; UTF8 mail = ""; ContactAddressType addressType = ContactAddressType::OTHER; UTF8 assetPath = ""; UTF8 speeddial = ""; std::set groups = {}; enum class NameFormatType { Default, List, NotUseNumber, Title, }; inline auto getNumberAsName() const -> UTF8 { if (numbers.size() > 0 && numbers[0].number.getEntered().size() > 0) { return numbers[0].number.getFormatted(); } if (numbers.size() > 1 && numbers[1].number.getEntered().size() > 0) { return numbers[1].number.getFormatted(); } return ""; } inline auto getFormattedName(const NameFormatType type = NameFormatType::Default) const -> UTF8 { if (isTemporary()) { debug_db_data("temporary contact, number as name: '%s'", getNumberAsName().c_str()); return getNumberAsName(); } if (primaryName.length() > 0) { return alternativeName.length() > 0 ? primaryName + " " + alternativeName : primaryName; } if (alternativeName.length() > 0) { return alternativeName; } if (type == NameFormatType::NotUseNumber) { return ""; } if ((type == NameFormatType::Default || type == NameFormatType::List) && getNumberAsName().length() > 0) { return getNumberAsName(); } if (type == NameFormatType::List || type == NameFormatType::Title) { return utils::localize.get("app_phonebook_contact_no_name"); } return ""; } auto getAsString() const -> std::string { std::stringstream contactData; if (getFormattedName(NameFormatType::NotUseNumber).length() > 0) { contactData << getFormattedName(NameFormatType::NotUseNumber) << gui::text::newline; } if (numbers.size() > 0 && numbers[0].number.getEntered().size() > 0) { contactData << numbers[0].number.getFormatted() << gui::text::newline; } if (numbers.size() > 1 && numbers[1].number.getEntered().size() > 0) { contactData << numbers[1].number.getFormatted() << gui::text::newline; } if (mail.length() > 0) { contactData << mail << gui::text::newline; } if (address.length() > 0) { contactData << address << gui::text::newline; } if (note.length() > 0) { contactData << note.c_str(); } return contactData.str(); } void addToFavourites(bool add); void addToIce(bool add); void addToBlocked(bool add); void addToGroup(uint32_t groupId); void removeFromGroup(uint32_t groupId); [[nodiscard]] auto isOnFavourites() const -> bool; [[nodiscard]] auto isOnIce() const -> bool; [[nodiscard]] auto isOnBlocked() const -> bool; [[nodiscard]] auto isOnGroup(uint32_t groupId) const -> bool; [[nodiscard]] auto isTemporary() const -> bool; }; enum class ContactRecordField { PrimaryName, NumberE164, NumberUser, SpeedDial, Groups, }; class ContactNumberHolder { private: ContactsNumberTableRow row; utils::PhoneNumber number; public: ContactNumberHolder(ContactsNumberTableRow numberRow); auto getNumber() const -> const utils::PhoneNumber &; auto getContactID() const -> std::uint32_t; auto getNumberID() const -> std::uint32_t; }; class ContactRecordInterface : public RecordInterface { public: struct ContactNumberMatch { ContactRecord contact; std::uint32_t contactId = DB_ID_NONE; std::uint32_t numberId = DB_ID_NONE; ContactNumberMatch(ContactRecord rec, std::uint32_t contactId, std::uint32_t numberId); }; ContactRecordInterface(ContactsDB *db); ~ContactRecordInterface() override = default; auto Add(ContactRecord &rec) -> bool final; auto RemoveByID(uint32_t id) -> bool final; auto Update(const ContactRecord &rec) -> bool final; auto BlockByID(uint32_t id, const bool shouldBeBlocked = true) -> bool; auto GetByID(uint32_t id) -> ContactRecord final; auto GetByIdWithTemporary(uint32_t id) -> ContactRecord; auto GetCount() -> uint32_t final; auto GetCountFavourites() -> uint32_t; auto GetLimitOffset(uint32_t offset, uint32_t limit) -> std::unique_ptr> final; auto GetLimitOffsetByField(uint32_t offset, uint32_t limit, ContactRecordField field, const char *str) -> std::unique_ptr> final; auto GetByName(UTF8 primaryName, UTF8 alternativeName) -> std::unique_ptr>; enum class CreateTempContact : bool { False, True }; auto GetByNumber(const UTF8 &number, CreateTempContact createTempContact = CreateTempContact::False) -> std::unique_ptr>; auto GetByNumber(const utils::PhoneNumber::View &numberView, CreateTempContact createTempContact = CreateTempContact::False) -> std::unique_ptr>; auto MatchByNumber(const utils::PhoneNumber::View &numberView, CreateTempContact createTempContact = CreateTempContact::False, utils::PhoneNumber::Match matchLevel = utils::PhoneNumber::Match::POSSIBLE) -> std::optional; auto GetBySpeedDial(UTF8 speedDial) -> std::unique_ptr>; auto Search(const char *primaryName, const char *alternativeName, const char *number) -> std::unique_ptr>; auto runQuery(std::shared_ptr query) -> std::unique_ptr override; auto GetNumberById(std::uint32_t numberId) -> utils::PhoneNumber::View; auto GetNumbersIdsByContact(std::uint32_t contactId) -> std::vector; private: ContactsDB *contactDB; /// get multiple numbers by split numbers_id auto getNumbers(const std::string &numbers_id) -> std::vector; auto getByIdCommon(ContactsTableRow &contact) -> ContactRecord; auto getContactByNumber(const UTF8 &number) -> std::unique_ptr>; auto getAllNumbers() -> std::vector; auto buildNumberMatcher(std::vector &contactNumberHolders) -> utils::NumberHolderMatcher; auto splitNumberIDs(const std::string &numberIDs) -> std::vector; auto joinNumberIDs(const std::vector &numberIDs) -> std::string; auto unbindNumber(std::uint32_t contactId, std::uint32_t numberId) -> bool; const std::uint32_t favouritesGroupId; auto getQuery(std::shared_ptr query) -> std::unique_ptr; auto getForListQuery(std::shared_ptr query) -> std::unique_ptr; auto getLetterMapQuery(std::shared_ptr query) -> std::unique_ptr; auto getByIDQuery(std::shared_ptr query) -> std::unique_ptr; auto getSizeQuery(std::shared_ptr query) -> std::unique_ptr; auto addQuery(std::shared_ptr query) -> std::unique_ptr; auto updateQuery(std::shared_ptr query) -> std::unique_ptr; auto removeQuery(std::shared_ptr query) -> std::unique_ptr; auto numberGetByIdQuery(std::shared_ptr query) -> std::unique_ptr; };