diff --git a/image/system_a/data/lang/Deutsch.json b/image/system_a/data/lang/Deutsch.json
index 5bf4600b3..1826689c2 100644
--- a/image/system_a/data/lang/Deutsch.json
+++ b/image/system_a/data/lang/Deutsch.json
@@ -716,5 +716,7 @@
"tethering_enable_question": "Sie sind mit dem Computer verbunden.
Tethering einschalten?
(einige Funktionen k\u00f6nnen deaktiviert sein)",
"tethering_menu_access_decline": "Tethering ist eingeschaltet.
Schalten Sie Tethering aus,
um auf das Men\u00fc zuzugreifen",
"tethering_phone_mode_change_prohibited": "Tethering ist eingeschaltet.
Andere Betriebsarten (Verbunden, DND,
Offline) werden von dieser Betriebsart \u00fcberlagert
und funktionieren nicht.",
- "tethering_turn_off_question": "Tethering ausschalten?"
+ "tethering_turn_off_question": "Tethering ausschalten?",
+ "unsaved_changes": "Ungespeicherte \u00c4nderungen",
+ "exit_without_saving": "M\u00f6chten Sie den Vorgang ohne Speichern beenden?"
}
diff --git a/image/system_a/data/lang/English.json b/image/system_a/data/lang/English.json
index b21fdc3dd..1f632fc5a 100644
--- a/image/system_a/data/lang/English.json
+++ b/image/system_a/data/lang/English.json
@@ -727,5 +727,7 @@
"tethering_enable_question": "You're connected to the computer.
Turn tethering on?
(some functions may be disabled)",
"tethering_menu_access_decline": "Tethering is on.
To access menu,
turn tethering off.",
"tethering_phone_mode_change_prohibited": "Tethering is on.
Other modes (Connected, DND,
Offline) are overriden by this mode
and are not working.",
- "tethering_turn_off_question": "Turn tethering off?"
+ "tethering_turn_off_question": "Turn tethering off?",
+ "unsaved_changes": "Unsaved changes",
+ "exit_without_saving": "Do you want to exit
without saving?"
}
diff --git a/image/system_a/data/lang/Espanol.json b/image/system_a/data/lang/Espanol.json
index 3bdb0d309..fda26f113 100644
--- a/image/system_a/data/lang/Espanol.json
+++ b/image/system_a/data/lang/Espanol.json
@@ -716,5 +716,7 @@
"tethering_enable_question": "Est\u00e1s conectado al ordenador.
\u00bfActivar el anclaje de red?
(algunas funciones podr\u00edan desactivarse)",
"tethering_menu_access_decline": "El anclaje de red est\u00e1 activado.
Para acceder al men\u00fa,
desactiva el tethering.",
"tethering_phone_mode_change_prohibited": "El anclaje de red est\u00e1 activado.
Este modo anula otros modos (Conectado, No molestar,
Desconectado)
y hace que dejen de funcionar.",
- "tethering_turn_off_question": "\u00bfDesactivar el anclaje de red?"
+ "tethering_turn_off_question": "\u00bfDesactivar el anclaje de red?",
+ "unsaved_changes": "Cambios no guardados",
+ "exit_without_saving": "\u00bfQuieres salir sin guardar?"
}
diff --git a/image/system_a/data/lang/Francais.json b/image/system_a/data/lang/Francais.json
index 8219999cb..52880199b 100644
--- a/image/system_a/data/lang/Francais.json
+++ b/image/system_a/data/lang/Francais.json
@@ -687,5 +687,7 @@
"tethering_enable_question": "Vous \u00eates connect\u00e9 \u00e0 l'ordinateur.
Voulez-vous activer le partage de connexion?
(certaines fonctions peuvent \u00eatre d\u00e9sactiv\u00e9es)",
"tethering_menu_access_decline": "Le partage de connexion est activ\u00e9.
Pour acc\u00e9der au menu, veuillez
d\u00e9sactiver le partage de connextion.",
"tethering_phone_mode_change_prohibited": "Le partage de connexion est activ\u00e9.
Ce mode-ci remplace et d\u00e9sactive les autres modes
(Connect\u00e9, NPD, Hors ligne)",
- "tethering_turn_off_question": "Voulez-vous d\u00e9sactiver le partage de connexion?"
+ "tethering_turn_off_question": "Voulez-vous d\u00e9sactiver le partage de connexion?",
+ "unsaved_changes": "Modifications non enregistr\u00e9es",
+ "exit_without_saving": "Voulez-vous quitter sans sauvegarder ?"
}
diff --git a/image/system_a/data/lang/Polski.json b/image/system_a/data/lang/Polski.json
index 14d38df14..bd31fe51f 100644
--- a/image/system_a/data/lang/Polski.json
+++ b/image/system_a/data/lang/Polski.json
@@ -715,5 +715,7 @@
"tethering_enable_question": "Po\u0142\u0105czono z komputerem.
W\u0142\u0105czy\u0107 tethering?
(Niekt\u00f3re funkcje mog\u0105 by\u0107 niedost\u0119pne)",
"tethering_menu_access_decline": "Tethering w\u0142\u0105czony.
Aby przej\u015b\u0107 do menu,
wy\u0142\u0105cz tethering.",
"tethering_phone_mode_change_prohibited": "Tethering w\u0142\u0105czony.
Ten tryb powoduje, \u017ce inne tryby (Po\u0142\u0105czony, Nie przeszkadza\u0107,
Offline) nie dzia\u0142aj\u0105.",
- "tethering_turn_off_question": "Wy\u0142\u0105czy\u0107 tethering?"
+ "tethering_turn_off_question": "Wy\u0142\u0105czy\u0107 tethering?",
+ "unsaved_changes": "Niezapisane zmiany",
+ "exit_without_saving": "Czy chcesz wyj\u015b\u0107
bez zapisywania?"
}
diff --git a/image/system_a/data/lang/Svenska.json b/image/system_a/data/lang/Svenska.json
index 2d655f90d..4f30316d7 100644
--- a/image/system_a/data/lang/Svenska.json
+++ b/image/system_a/data/lang/Svenska.json
@@ -526,5 +526,7 @@
"tethering_menu_access_decline": "Internetdelning \u00e4r p\u00e5.
F\u00f6r att \u00f6ppna menyn,
st\u00e4ng av internetdelning.",
"tethering_phone_mode_change_prohibited": "Internetdelning \u00e4r p\u00e5.
Andra l\u00e4gen (ansluten, DND,
offline) \u00e5sidos\u00e4tts av detta
l\u00e4ge och fungerar inte.",
"tethering_turn_off_question": "St\u00e4nga av Internetdelning?",
- "volume_text": "LJUDVOLYM"
+ "volume_text": "LJUDVOLYM",
+ "unsaved_changes": "Osparade \u00e4ndringar",
+ "exit_without_saving": "Vill du g\u00e5 h\u00e4rifr\u00e5n utan att spara?"
}
diff --git a/module-apps/application-notes/ApplicationNotes.cpp b/module-apps/application-notes/ApplicationNotes.cpp
index e0d68de35..7f99a5b94 100644
--- a/module-apps/application-notes/ApplicationNotes.cpp
+++ b/module-apps/application-notes/ApplicationNotes.cpp
@@ -124,6 +124,10 @@ namespace app
windowsFactory.attach(window::name::option_window, [](ApplicationCommon *app, const std::string &name) {
return std::make_unique(app, name);
});
+ windowsFactory.attach(gui::name::window::notes_dialog_yes_no,
+ [](ApplicationCommon *app, const std::string &name) {
+ return std::make_unique(app, name);
+ });
attachPopups({gui::popup::ID::Volume,
gui::popup::ID::Tethering,
diff --git a/module-apps/application-notes/include/application-notes/ApplicationNotes.hpp b/module-apps/application-notes/include/application-notes/ApplicationNotes.hpp
index 7c8384f68..b53fac357 100644
--- a/module-apps/application-notes/include/application-notes/ApplicationNotes.hpp
+++ b/module-apps/application-notes/include/application-notes/ApplicationNotes.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ -14,6 +14,7 @@ namespace gui::name::window
inline constexpr auto notes_search_result = "NotesSearchResult";
inline constexpr auto note_dialog = "Dialog";
inline constexpr auto note_confirm_dialog = "ConfirmDialog";
+ inline constexpr auto notes_dialog_yes_no = "DialogYesNo";
} // namespace gui::name::window
namespace app
diff --git a/module-apps/application-notes/windows/NoteEditWindow.cpp b/module-apps/application-notes/windows/NoteEditWindow.cpp
index a69afe570..b0f2a4f4d 100644
--- a/module-apps/application-notes/windows/NoteEditWindow.cpp
+++ b/module-apps/application-notes/windows/NoteEditWindow.cpp
@@ -2,6 +2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "NoteEditWindow.hpp"
+#include "DialogMetadataMessage.hpp"
#include
@@ -155,6 +156,24 @@ namespace app::notes
std::make_unique(noteEditOptions(application, edit)));
}
}
+ if (isCurrentTextDifferentThanSaved() &&
+ (inputEvent.isShortRelease(gui::KeyCode::KEY_RF) || inputEvent.isLongRelease(gui::KeyCode::KEY_RF))) {
+
+ // Show a popup warning about possible data loss
+ auto metaData = std::make_unique(
+ gui::DialogMetadata{utils::translate("unsaved_changes"),
+ "delete_128px_W_G",
+ utils::translate("exit_without_saving"),
+ "",
+ [=]() -> bool {
+ application->returnToPreviousWindow(); // To exit this popup
+ application->returnToPreviousWindow(); // To switch back to previous window
+ return true;
+ }});
+
+ application->switchWindow(gui::name::window::notes_dialog_yes_no, std::move(metaData));
+ return true;
+ }
return AppWindow::onInput(inputEvent);
}
@@ -169,4 +188,9 @@ namespace app::notes
{
return (edit != nullptr) ? edit->isEmpty() : true;
}
+
+ bool NoteEditWindow::isCurrentTextDifferentThanSaved()
+ {
+ return notesRecord->snippet != edit->getText();
+ }
} // namespace app::notes
diff --git a/module-apps/application-notes/windows/NoteEditWindow.hpp b/module-apps/application-notes/windows/NoteEditWindow.hpp
index 43ebd1676..f399718c4 100644
--- a/module-apps/application-notes/windows/NoteEditWindow.hpp
+++ b/module-apps/application-notes/windows/NoteEditWindow.hpp
@@ -42,6 +42,7 @@ namespace app::notes
void setCharactersCount(std::uint32_t count);
void setNoteText(const UTF8 &text);
void saveNote();
+ bool isCurrentTextDifferentThanSaved();
std::unique_ptr presenter;
std::shared_ptr notesRecord;
diff --git a/module-apps/application-phonebook/models/NewContactModel.cpp b/module-apps/application-phonebook/models/NewContactModel.cpp
index 625606455..6fd9d73e7 100644
--- a/module-apps/application-phonebook/models/NewContactModel.cpp
+++ b/module-apps/application-phonebook/models/NewContactModel.cpp
@@ -235,3 +235,14 @@ void NewContactModel::openTextOptions(gui::Text *text)
auto data = std::make_unique(text);
application->switchWindow(gui::window::name::input_options, std::move(data));
}
+bool NewContactModel::isAnyUnsavedChange(std::shared_ptr contactRecord)
+{
+ for (const auto &item : internalData) {
+ if (item->onCheckUnsavedChangeCallback) {
+ if (item->onCheckUnsavedChangeCallback(contactRecord)) {
+ return true;
+ }
+ }
+ }
+ return false; // there is no change between already provided data and saved ones
+}
diff --git a/module-apps/application-phonebook/models/NewContactModel.hpp b/module-apps/application-phonebook/models/NewContactModel.hpp
index 43474d548..6e2304615 100644
--- a/module-apps/application-phonebook/models/NewContactModel.hpp
+++ b/module-apps/application-phonebook/models/NewContactModel.hpp
@@ -28,6 +28,7 @@ class NewContactModel : public app::InternalModel, publi
void createData();
bool verifyData();
bool emptyData();
+ bool isAnyUnsavedChange(std::shared_ptr contactRecord);
[[nodiscard]] auto getRequestType() -> PhonebookItemData::RequestType;
[[nodiscard]] auto requestRecordsCount() -> unsigned int override;
diff --git a/module-apps/application-phonebook/widgets/InputBoxWithLabelAndIconWidget.cpp b/module-apps/application-phonebook/widgets/InputBoxWithLabelAndIconWidget.cpp
index 01284a1c6..28f986fc8 100644
--- a/module-apps/application-phonebook/widgets/InputBoxWithLabelAndIconWidget.cpp
+++ b/module-apps/application-phonebook/widgets/InputBoxWithLabelAndIconWidget.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "InputBoxWithLabelAndIconWidget.hpp"
@@ -172,6 +172,9 @@ namespace gui
onLoadCallback = [&](std::shared_ptr contact) {
tickImage->visible = contact->isOnFavourites();
};
+ onCheckUnsavedChangeCallback = [&](std::shared_ptr contact) {
+ return tickImage->visible != contact->isOnFavourites();
+ };
}
void InputBoxWithLabelAndIconWidget::addToICEHandler()
{
@@ -214,6 +217,9 @@ namespace gui
};
onSaveCallback = [&](std::shared_ptr contact) { contact->addToIce(tickImage->visible); };
onLoadCallback = [&](std::shared_ptr contact) { tickImage->visible = contact->isOnIce(); };
+ onCheckUnsavedChangeCallback = [&](std::shared_ptr contact) {
+ return tickImage->visible != contact->isOnIce();
+ };
}
} /* namespace gui */
diff --git a/module-apps/application-phonebook/widgets/InputLinesWithLabelWidget.cpp b/module-apps/application-phonebook/widgets/InputLinesWithLabelWidget.cpp
index 6fc66ced5..192847188 100644
--- a/module-apps/application-phonebook/widgets/InputLinesWithLabelWidget.cpp
+++ b/module-apps/application-phonebook/widgets/InputLinesWithLabelWidget.cpp
@@ -163,6 +163,10 @@ namespace gui
onSaveCallback = [&](std::shared_ptr contact) { contact->primaryName = inputText->getText(); };
onLoadCallback = [&](std::shared_ptr contact) { inputText->setText(contact->primaryName); };
onEmptyCallback = [&]() { return inputText->isEmpty(); };
+
+ onCheckUnsavedChangeCallback = [&](std::shared_ptr contact) {
+ return contact->primaryName != inputText->getText();
+ };
}
void InputLinesWithLabelWidget::secondNameHandler()
{
@@ -176,6 +180,10 @@ namespace gui
};
onLoadCallback = [&](std::shared_ptr contact) { inputText->setText(contact->alternativeName); };
onEmptyCallback = [&]() { return inputText->isEmpty(); };
+
+ onCheckUnsavedChangeCallback = [&](std::shared_ptr contact) {
+ return contact->alternativeName != inputText->getText();
+ };
}
void InputLinesWithLabelWidget::numberHandler()
{
@@ -208,6 +216,11 @@ namespace gui
};
onEmptyCallback = [&]() { return inputText->isEmpty(); };
+
+ onCheckUnsavedChangeCallback = [&](std::shared_ptr contact) {
+ std::string savedNumber = (!contact->numbers.empty()) ? (contact->numbers[0].number.getEntered()) : "";
+ return savedNumber != std::string(inputText->getText());
+ };
}
void InputLinesWithLabelWidget::secondNumberHandler()
{
@@ -241,6 +254,11 @@ namespace gui
};
onEmptyCallback = [&]() { return inputText->isEmpty(); };
+
+ onCheckUnsavedChangeCallback = [&](std::shared_ptr contact) {
+ std::string savedNumber = (contact->numbers.size() > 1) ? (contact->numbers[1].number.getEntered()) : "";
+ return savedNumber != std::string(inputText->getText());
+ };
}
void InputLinesWithLabelWidget::emailHandler()
{
@@ -252,6 +270,10 @@ namespace gui
onSaveCallback = [&](std::shared_ptr contact) { contact->mail = inputText->getText(); };
onLoadCallback = [&](std::shared_ptr contact) { inputText->setText(contact->mail); };
onEmptyCallback = [&]() { return inputText->isEmpty(); };
+
+ onCheckUnsavedChangeCallback = [&](std::shared_ptr contact) {
+ return contact->mail != inputText->getText();
+ };
}
void InputLinesWithLabelWidget::addressHandler()
{
@@ -262,6 +284,10 @@ namespace gui
onSaveCallback = [&](std::shared_ptr contact) { contact->address = inputText->getText(); };
onLoadCallback = [&](std::shared_ptr contact) { inputText->setText(contact->address); };
+
+ onCheckUnsavedChangeCallback = [&](std::shared_ptr contact) {
+ return contact->address != inputText->getText();
+ };
}
void InputLinesWithLabelWidget::noteHandler()
{
@@ -272,6 +298,10 @@ namespace gui
onSaveCallback = [&](std::shared_ptr contact) { contact->note = inputText->getText(); };
onLoadCallback = [&](std::shared_ptr contact) { inputText->setText(contact->note); };
+
+ onCheckUnsavedChangeCallback = [&](std::shared_ptr contact) {
+ return contact->note != inputText->getText();
+ };
}
} /* namespace gui */
diff --git a/module-apps/application-phonebook/windows/PhonebookNewContact.cpp b/module-apps/application-phonebook/windows/PhonebookNewContact.cpp
index 92885afc7..188e7fdbb 100644
--- a/module-apps/application-phonebook/windows/PhonebookNewContact.cpp
+++ b/module-apps/application-phonebook/windows/PhonebookNewContact.cpp
@@ -115,6 +115,22 @@ namespace gui
return true;
}
+ void PhonebookNewContact::showDialogUnsavedChanges(std::function whereToGoOnYes)
+ {
+ // Show a popup warning about possible data loss
+ auto metaData = std::make_unique(
+ gui::DialogMetadata{utils::translate("unsaved_changes"),
+ "delete_128px_W_G",
+ utils::translate("exit_without_saving"),
+ "",
+ [=]() -> bool {
+ application->returnToPreviousWindow(); // To exit this popup
+ return whereToGoOnYes();
+ }});
+
+ application->switchWindow(gui::window::name::dialog_yes_no, std::move(metaData));
+ }
+
void PhonebookNewContact::setSaveButtonVisible(bool visible)
{
navBar->setActive(nav_bar::Side::Center, visible);
@@ -135,14 +151,31 @@ namespace gui
return true;
}
else if (!inputEvent.isShortRelease(KeyCode::KEY_RF) || !shouldCurrentAppBeIgnoredOnSwitchBack()) {
+ if (areUnsavedChanges()) {
+ if (inputEvent.isShortRelease(gui::KeyCode::KEY_RF) || inputEvent.isLongRelease(gui::KeyCode::KEY_RF)) {
+ showDialogUnsavedChanges([this]() {
+ application->returnToPreviousWindow();
+ return true;
+ });
+ return true;
+ }
+ }
return AppWindow::onInput(inputEvent);
}
- return shouldCurrentAppBeIgnoredOnSwitchBack()
- ? app::manager::Controller::switchBack(
- application,
- std::make_unique(nameOfPreviousApplication.value()))
- : true;
+ auto returnWhenCurrentAppShouldBeIgnoredOnSwitchBack = [this]() {
+ return shouldCurrentAppBeIgnoredOnSwitchBack()
+ ? app::manager::Controller::switchBack(
+ application,
+ std::make_unique(nameOfPreviousApplication.value()))
+ : true;
+ };
+
+ if (areUnsavedChanges()) {
+ showDialogUnsavedChanges(returnWhenCurrentAppShouldBeIgnoredOnSwitchBack);
+ return true;
+ }
+ return returnWhenCurrentAppShouldBeIgnoredOnSwitchBack();
}
auto PhonebookNewContact::verifyAndSave() -> bool
@@ -207,38 +240,37 @@ namespace gui
DBServiceAPI::MatchContactByPhoneNumber(application, duplicatedNumber, duplicatedNumberContactID);
const auto oldContactRecord = (matchedContact != nullptr) ? *matchedContact : ContactRecord{};
- auto metaData = std::make_unique(
- gui::DialogMetadata{duplicatedNumber.getFormatted(),
- "info_128px_W_G",
- text::RichTextParser()
- .parse(utils::translate("app_phonebook_duplicate_numbers"),
- nullptr,
- gui::text::RichTextParser::TokenMap(
- {{"$CONTACT_FORMATTED_NAME$", oldContactRecord.getFormattedName()}}))
- ->getText(),
- "",
- [=]() -> bool {
- if (contactAction == ContactAction::Add) {
- contact->ID = oldContactRecord.ID;
- }
- if (!DBServiceAPI::ContactUpdate(application, *contact)) {
- LOG_ERROR("Contact id=%" PRIu32 " update failed", contact->ID);
- return false;
- }
+ auto metaData = std::make_unique(gui::DialogMetadata{
+ duplicatedNumber.getFormatted(),
+ "info_128px_W_G",
+ text::RichTextParser()
+ .parse(utils::translate("app_phonebook_duplicate_numbers"),
+ nullptr,
+ gui::text::RichTextParser::TokenMap(
+ {{"$CONTACT_FORMATTED_NAME$", oldContactRecord.getFormattedName()}}))
+ ->getText(),
+ "",
+ [=]() -> bool {
+ if (contactAction == ContactAction::Add) {
+ contact->ID = oldContactRecord.ID;
+ }
+ if (!DBServiceAPI::ContactUpdate(application, *contact)) {
+ LOG_ERROR("Contact id=%" PRIu32 " update failed", contact->ID);
+ return false;
+ }
- /* Pop "Add contact" window from the stack so that clicking
- * back button after saving the modified contact returns to
- * contacts list, not to the "Add contact" window. */
- application->popWindow(gui::window::name::new_contact);
+ /* Pop "Add contact" window from the stack so that clicking
+ * back button after saving the modified contact returns to
+ * contacts list, not to the "Add contact" window. */
+ application->popWindow(gui::window::name::new_contact);
- /* Switch to contact details */
- auto switchData =
- std::make_unique(contact, newContactModel->getRequestType());
- switchData->ignoreCurrentWindowOnStack = true;
- application->switchWindow(gui::window::name::contact, std::move(switchData));
+ /* Switch to contact details */
+ auto switchData = std::make_unique(contact, newContactModel->getRequestType());
+ switchData->ignoreCurrentWindowOnStack = true;
+ application->switchWindow(gui::window::name::contact, std::move(switchData));
- return true;
- }});
+ return true;
+ }});
application->switchWindow(gui::window::name::dialog_yes_no, std::move(metaData));
}
@@ -301,5 +333,9 @@ namespace gui
contactByID->front().primaryName.empty() and contactByID->front().alternativeName.empty() and
contactByID->front().numbers.empty();
}
+ bool PhonebookNewContact::areUnsavedChanges() const
+ {
+ return newContactModel->isAnyUnsavedChange(contact);
+ }
} // namespace gui
diff --git a/module-apps/application-phonebook/windows/PhonebookNewContact.hpp b/module-apps/application-phonebook/windows/PhonebookNewContact.hpp
index b48dddf53..3cd59a53d 100644
--- a/module-apps/application-phonebook/windows/PhonebookNewContact.hpp
+++ b/module-apps/application-phonebook/windows/PhonebookNewContact.hpp
@@ -38,9 +38,11 @@ namespace gui
void showDialogDuplicatedNumber(const utils::PhoneNumber::View &duplicatedNumber,
const std::uint32_t duplicatedNumberContactID = 0u);
void showDialogDuplicatedSpeedDialNumber();
+ void showDialogUnsavedChanges(std::function whereToGoOnYes = nullptr);
void setSaveButtonVisible(bool visible);
void showContactDeletedNotification();
bool checkIfContactWasDeletedDuringEditProcess() const;
+ bool areUnsavedChanges() const;
std::shared_ptr contact = nullptr;
std::shared_ptr newContactModel = nullptr;
diff --git a/module-gui/gui/widgets/ListItem.hpp b/module-gui/gui/widgets/ListItem.hpp
index ae260ba1f..88643c476 100644
--- a/module-gui/gui/widgets/ListItem.hpp
+++ b/module-gui/gui/widgets/ListItem.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ -22,10 +22,11 @@ namespace gui
class ListItemWithCallbacks : public ListItem
{
public:
- std::function onEmptyCallback = nullptr;
- std::function onContentChangedCallback = nullptr;
- std::function onVerifyCallback = nullptr;
- std::function record)> onSaveCallback = nullptr;
- std::function record)> onLoadCallback = nullptr;
+ std::function onEmptyCallback = nullptr;
+ std::function onContentChangedCallback = nullptr;
+ std::function onVerifyCallback = nullptr;
+ std::function record)> onSaveCallback = nullptr;
+ std::function record)> onLoadCallback = nullptr;
+ std::function record)> onCheckUnsavedChangeCallback = nullptr;
};
} /* namespace gui */
diff --git a/pure_changelog.md b/pure_changelog.md
index 59a440be7..e5a502bd0 100644
--- a/pure_changelog.md
+++ b/pure_changelog.md
@@ -37,6 +37,7 @@
* Fixed missing tethering icon on "Tethering is on" window
* Fixed showing "Copy text" option in empty note
* Fixed "Copy" option missing from the options list in "New message" window
+* Fixed losing unsaved data on go back
## [1.7.2 2023-07-28]