From c2a31a3516d4918a4a047b59079074dbfad05646 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+drsoliddevil@users.noreply.github.com>
Date: Thu, 10 Jul 2025 19:22:48 +0200
Subject: [PATCH 01/23] Added pull-request templates
---
.github/PULL_REQUEST_TEMPLATE.md | 5 +++++
.../pull_request_bug_template.md | 20 +++++++++++++++++++
.../pull_request_general_template.md | 18 +++++++++++++++++
.../pull_request_release_template.md | 9 +++++++++
4 files changed, 52 insertions(+)
create mode 100644 .github/PULL_REQUEST_TEMPLATE.md
create mode 100644 .github/PULL_REQUEST_TEMPLATE/pull_request_bug_template.md
create mode 100644 .github/PULL_REQUEST_TEMPLATE/pull_request_general_template.md
create mode 100644 .github/PULL_REQUEST_TEMPLATE/pull_request_release_template.md
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..f0db9a6
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,5 @@
+Choose template:
+ - [General](?expand=1&template=pull_request_general_template.md)
+ - [Bug](?expand=1&template=pull_request_bug_template.md)
+ - [Release](?expand=1&template=pull_request_release_template.md)
+
\ No newline at end of file
diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_bug_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_bug_template.md
new file mode 100644
index 0000000..a215efd
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_bug_template.md
@@ -0,0 +1,20 @@
+### Description
+*Please explain the changes you made here.*
+
+### Checklist
+- [ ] Check your code additions will fail neither code linting checks nor unit test.
+- [ ] Associated issues have been linked.
+- [ ] Performed a self-review of my own code.
+
+### What is the current behavior?
+*Please describe the current behavior that you are modifying.*
+
+### What is the new behavior?
+*Please describe the behavior or changes that are being added by this PR.*
+
+### Where has this been tested?
+ - **Device:** (e.g. Asus Zenfone 11)
+ - **Android Version:** (e.g. Android 16)
+
+### Further comments
+If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...
diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_general_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_general_template.md
new file mode 100644
index 0000000..e81226c
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_general_template.md
@@ -0,0 +1,18 @@
+### Description
+*Please explain the changes you made here.*
+
+### Checklist
+- [ ] Check your code additions will fail neither code linting checks nor unit test.
+- [ ] Associated issues have been linked.
+- [ ] Performed a self-review of my own code.
+
+### Does this introduce a breaking change?
+- [ ] Yes
+- [ ] No
+
+### Where has this been tested?
+ - **Device:** (e.g. Asus Zenfone 11)
+ - **Android Version:** (e.g. Android 16)
+
+### Further comments
+If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...
diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_release_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_release_template.md
new file mode 100644
index 0000000..787f598
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_release_template.md
@@ -0,0 +1,9 @@
+### Breaking Changes
+
+### New Features
+
+### Bug Fixes
+
+### Performance Improvements
+
+### Other Changes
\ No newline at end of file
From 3e8177cd76368379a5eb42b556e45deeac08435d Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Thu, 10 Jul 2025 19:52:36 +0200
Subject: [PATCH 02/23] Created changelog
---
CHANGELOG.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
create mode 100644 CHANGELOG.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..6807534
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,71 @@
+## [1.0.3-beta](https://github.com/DrSolidDevil/Vidar/compare/v1.0.2-beta...v1.0.3-beta) (2025-07-10)
+
+> No real changes for the end user; upgrading is not necessary.
+
+### Other Changes
+* Change license from 3-Clause BSD to Mozilla Public License Version 2.0 [`87bed3f`](https://github.com/DrSolidDevil/Vidar/commit/87bed3ffa831e00e8a6e235bb8129a0292bd92b6)
+* Added version validation for pushing to main. [`c259588`](https://github.com/DrSolidDevil/Vidar/commit/c2595885e4b817f1c397bba621fef352911f4322)
+
+
+
+## [1.0.2-beta](https://github.com/DrSolidDevil/Vidar/compare/v1.0.1-beta...v1.0.2-beta) (2025-07-09)
+
+> Very minor changes relating to some refactoring and logging. No real changes for the end user; upgrading is not necessary.
+
+### Other Changes
+* Made encryption error messages public and made message_bar.dart use these when checking for specific error type in switch. [`8315d69`](https://github.com/DrSolidDevil/Vidar/commit/8315d69f60a2fafc2e6bf924f12d846cb2b6dd71)
+* Added info to log in encryptMessage when no key exists, informing if it is allowed or not. [`de0478d`](https://github.com/DrSolidDevil/Vidar/commit/de0478d16ce98aff72281f64a752e21ae1ebad4e)
+
+
+
+## [1.0.1-beta](https://github.com/DrSolidDevil/Vidar/compare/v1.0.0-beta...v1.0.1-beta) (2025-07-08)
+
+> Minor patch relating to editing existing contacts and errors shown in the message bar.
+
+### Bug Fixes
+* Fixed error widget from message bar not adapting to changes in viewinsets (i.e. keyboard). [`c9bc4b9`](https://github.com/DrSolidDevil/Vidar/commit/c9bc4b91c5e586df7a33b3244028f5fb398a0780)
+* Fixed displaying of error widget when transitioning from keyboard being up to it being down or vice versa. [`c9bc4b9`](https://github.com/DrSolidDevil/Vidar/commit/c9bc4b91c5e586df7a33b3244028f5fb398a0780)
+
+### Other Changes
+* If a user forgets to enter a plus sign before the phone number it automatically adds it. [`a5f4980`](https://github.com/DrSolidDevil/Vidar/commit/a5f49804b6a098089a340949bb560215330c184d)
+* Editing existing contact's details is now subject to a check of contact information invalidity. [`a5f4980`](https://github.com/DrSolidDevil/Vidar/commit/a5f49804b6a098089a340949bb560215330c184d)
+* Display time for errors related to sending messages and the message bar is extended to 15 seconds. [`c9bc4b9`](https://github.com/DrSolidDevil/Vidar/commit/c9bc4b91c5e586df7a33b3244028f5fb398a0780)
+
+
+
+## [1.0.0-beta](https://github.com/DrSolidDevil/Vidar/compare/v0.1.0...v1.0.0-beta) (2025-07-07)
+
+> This release marks a major milestone in Vidar's development. While still in beta, it introduces a wide range of new features, performance improvements, and changes that bring Vidar closer to a stable 1.0 release.
+
+### Breaking Changes
+* Made key storage encrypted using [flutter_secure_storage](https://pub.dev/packages/flutter_secure_storage). [`489d3af`](https://github.com/DrSolidDevil/Vidar/commit/489d3af688163e74ca035663ed842b2bfb712288)
+* APK package name renamed from `com.vidar.vidar` to `com.drsoliddevil.vidar`. This may affect upgrades and backups. [`2bd9cae`](https://github.com/DrSolidDevil/Vidar/commit/2bd9caee388cdc80218a83908ac7a4872d05ba76)
+
+
+### New Features
+* Ability to delete contacts from contact list by holding on the contact badge (i.e. long press). [`42f5681`](https://github.com/DrSolidDevil/Vidar/commit/42f5681ca3140c1b021c72dd6f3ace0f87726775)
+* Loading screen while you load a conversation. [`be5e0b9`](https://github.com/DrSolidDevil/Vidar/commit/be5e0b9ed0bfbda1ea01014b00c7d297ae541368)
+* Ability to wipe all keys with one button (in settings). [`cd466ea`](https://github.com/DrSolidDevil/Vidar/commit/cd466eae30f804ad5e1afd9be6bf734699660792)
+* System for logging with ability to export logs. [`33d1972`](https://github.com/DrSolidDevil/Vidar/commit/33d1972c4e7393860a19a2b2aeaba958f69adf05) [`95f4a7d`](https://github.com/DrSolidDevil/Vidar/commit/95f4a7d1c01fa282bfedc02500ecb9c5671cac4b) [`089dcd9`](https://github.com/DrSolidDevil/Vidar/commit/089dcd91ab6d52647888ae1b0517081770d5c0db) [`004c51d`](https://github.com/DrSolidDevil/Vidar/commit/004c51df68b2e33748c43915bf9c3ddf243931cf)
+
+### Bug Fixes
+* Fixed phone number parsing only applying to new contact. [`becca8a`](https://github.com/DrSolidDevil/Vidar/commit/becca8ae7f94f8f66ec7b237769b882df456182b)
+* Fixed SmsReceiver and SmsNotifier. [`7a6ede2`](https://github.com/DrSolidDevil/Vidar/commit/7a6ede25e8e04196d0c9d22ebe719049de034468) [`579a46d`](https://github.com/DrSolidDevil/Vidar/commit/579a46dcd5919782e3bcd2879661af8df5a12ac9) [`6629316`](https://github.com/DrSolidDevil/Vidar/commit/662931697ed4070d22bb80950e0ece5e3e92613f)
+
+### Performance Improvements
+* _generateRandomChar or _generateUniqueRandomInt does not need to create a new instance of Random every time they are called (if a Random object is provided via parameters). [`e9f8355`](https://github.com/DrSolidDevil/Vidar/commit/e9f8355e9fa0eb0b6e730b97a989697091351775)
+* decryptMessage does not need to create a new instance of AesGcm every time they are called (if a AesGcm object is provided via parameters). [`d47ebb8`](https://github.com/DrSolidDevil/Vidar/commit/d47ebb825653ad99f183cd4d90a22098c5c1f326)
+
+### Other Changes
+* Rewritten readme. [`5e33c19`](https://github.com/DrSolidDevil/Vidar/commit/5e33c19f4a9d61d294e678f68249639c5fc8a1d9)
+* Created a security policy. [`6c8dd32`](https://github.com/DrSolidDevil/Vidar/commit/6c8dd326d5da617fcbe9fbeeaf285fc0350e7313) [`ff7afa0`](https://github.com/DrSolidDevil/Vidar/commit/ff7afa0ba4fc3cb1611047bc20544eba36d41d3f) [`1c30221`](https://github.com/DrSolidDevil/Vidar/commit/1c30221b5e9b201a743ef783e44fb19b8309cdf4)
+* Created code of conduct (Contributor Covenant). [`f66ca46`](https://github.com/DrSolidDevil/Vidar/commit/f66ca46bc11f667c8541678ca7fab1f92c1a8f62) [`db2e83e`](https://github.com/DrSolidDevil/Vidar/commit/db2e83e6698d18eec29f9574c3f27d71437006dc)
+* Created workflows for building APK on new release and running linter before merge into main. [`fb4d988`](https://github.com/DrSolidDevil/Vidar/commit/fb4d988dc35944fd2930a07adc2ddfc99786d1a8)
+* Removed web-related code & files. [`130f03e`](https://github.com/DrSolidDevil/Vidar/commit/130f03e70e743318a50a2f20e76bc56aa48f8c40)
+* Messages with STATUS_FAILED will now be displayed as "MESSAGE_FAILED" in the conversation. [`bccae1c`](https://github.com/DrSolidDevil/Vidar/commit/bccae1c571472ed84238cc6db06b68db8efad7e7)
+* Message bar clears when a message is sent (without error). [`554e62c`](https://github.com/DrSolidDevil/Vidar/commit/554e62ce03b908a71b1fef1d3345a85133af89d4)
+* Chat updates when you send a message. [`110b2e2`](https://github.com/DrSolidDevil/Vidar/commit/110b2e2611224218c3e3028205e279d0c7dffbd4)
+* Buttons redesigned using TextButton. [`f3de296`](https://github.com/DrSolidDevil/Vidar/commit/f3de29691a4ff1e054f6e90d1916c6bcce236432)
+* Minor visual enhancements [`2540ad7`](https://github.com/DrSolidDevil/Vidar/commit/2540ad751c03dce39885fbb5b36551a3325a0962) [`fe025ee`](https://github.com/DrSolidDevil/Vidar/commit/fe025ee8cec4edd8eeb5ee0be77886747678fa97) [`454ce0c`](https://github.com/DrSolidDevil/Vidar/commit/454ce0cae7b3ddf7dfe74cbdf3344d227671de74)
+* Fixed typos. [`34a7a4a`](https://github.com/DrSolidDevil/Vidar/commit/34a7a4a4f2857c363fb0c5ee51c665a92f4a73c0) [`cd820ed`](https://github.com/DrSolidDevil/Vidar/commit/cd820edfd1927d5be5ad7bafcd83491c53deb695) [`f9fd354`](https://github.com/DrSolidDevil/Vidar/commit/f9fd3546b8b302165e051aacad63081b6504f579 )
+
From 642c3cb95b271b4a59e451042c7fba6dbc9c8198 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Fri, 11 Jul 2025 22:50:02 +0200
Subject: [PATCH 03/23] Added different colorsets for the app, at the moment
there are 3 excluding default..
---
lib/configuration.dart | 25 ++---
lib/pages/chat.dart | 12 +-
lib/pages/contact_list.dart | 20 ++--
lib/pages/edit_contact.dart | 49 +++++----
lib/pages/no_sms_permission.dart | 8 +-
lib/pages/settings_page.dart | 36 ++++--
lib/utils/colors.dart | 128 ++++++++++++++++++++++
lib/utils/settings.dart | 10 ++
lib/widgets/boolean_setting.dart | 15 +--
lib/widgets/color_set_select.dart | 75 +++++++++++++
lib/widgets/contact_badge.dart | 10 +-
lib/widgets/conversation_widget.dart | 8 +-
lib/widgets/loading_screen.dart | 7 +-
lib/widgets/message_bar.dart | 158 +++++++++++++++------------
lib/widgets/speech_bubble.dart | 7 +-
15 files changed, 407 insertions(+), 161 deletions(-)
create mode 100644 lib/utils/colors.dart
create mode 100644 lib/widgets/color_set_select.dart
diff --git a/lib/configuration.dart b/lib/configuration.dart
index 74373f3..a231629 100644
--- a/lib/configuration.dart
+++ b/lib/configuration.dart
@@ -1,23 +1,5 @@
-import "package:flutter/material.dart";
import "package:logging/logging.dart";
-class VidarColors {
- /// #1a1c28
- static const Color primaryDarkSpaceCadet = Color.fromARGB(255, 26, 28, 40);
-
- /// #64007b
- static const Color secondaryMetallicViolet = Color.fromARGB(255, 53, 22, 100);
-
- /// #b18c19
- static const Color tertiaryGold = Color.fromARGB(255, 177, 140, 25);
-
- /// #140627
- static const Color extraMidnightPurple = Color.fromARGB(255, 20, 6, 39);
-
- /// #b22222
- static const Color extraFireBrick = Color.fromARGB(255, 178, 34, 34);
-}
-
class CryptographicConfiguration {
// Length in bytes
static const int keyGenerationHashLength = 15;
@@ -48,6 +30,13 @@ class TimeConfiguration {
class MiscellaneousConfiguration {
static const String errorPrefix = "⚠";
+ static const List messageHints = [
+ "Write them a message!",
+ "Show them some love ❤️",
+ "Tell them your secrets 👀",
+ "Start gossiping...",
+ "Talk to them, they miss you.",
+ ];
}
class LoggingConfiguration {
diff --git a/lib/pages/chat.dart b/lib/pages/chat.dart
index 675bc8f..ceabb31 100644
--- a/lib/pages/chat.dart
+++ b/lib/pages/chat.dart
@@ -1,9 +1,9 @@
import "package:flutter/material.dart";
-import "package:vidar/configuration.dart";
import "package:vidar/pages/contact_list.dart";
import "package:vidar/pages/edit_contact.dart";
import "package:vidar/utils/contact.dart";
import "package:vidar/utils/navigation.dart";
+import "package:vidar/utils/settings.dart";
import "package:vidar/widgets/conversation_widget.dart";
import "package:vidar/widgets/message_bar.dart";
@@ -28,12 +28,12 @@ class _ChatPageState extends State {
@override
Widget build(final BuildContext context) => Scaffold(
appBar: AppBar(
- backgroundColor: VidarColors.secondaryMetallicViolet,
+ backgroundColor: Settings.colorSet.secondary,
title: Text(
contact.name,
- style: const TextStyle(
+ style: TextStyle(
fontSize: 18,
- color: Colors.white,
+ color: Settings.colorSet.text,
decoration: TextDecoration.none,
),
),
@@ -44,7 +44,7 @@ class _ChatPageState extends State {
onPressed: () {
clearNavigatorAndPush(context, const ContactListPage());
},
- icon: const Icon(Icons.arrow_back, color: Colors.white),
+ icon: Icon(Icons.arrow_back, color: Settings.colorSet.text),
tooltip: "Go back",
),
),
@@ -59,7 +59,7 @@ class _ChatPageState extends State {
EditContactPage(contact, ContactPageCaller.chatPage),
);
},
- icon: const Icon(Icons.edit, color: Colors.white),
+ icon: Icon(Icons.edit, color: Settings.colorSet.text),
tooltip: "Edit",
),
),
diff --git a/lib/pages/contact_list.dart b/lib/pages/contact_list.dart
index 421030e..d952988 100644
--- a/lib/pages/contact_list.dart
+++ b/lib/pages/contact_list.dart
@@ -1,10 +1,10 @@
import "package:flutter/material.dart";
-import "package:vidar/configuration.dart";
import "package:vidar/pages/edit_contact.dart";
import "package:vidar/pages/settings_page.dart";
import "package:vidar/utils/common_object.dart";
import "package:vidar/utils/contact.dart";
import "package:vidar/utils/navigation.dart";
+import "package:vidar/utils/settings.dart";
class ContactListPage extends StatefulWidget {
const ContactListPage({super.key});
@@ -24,15 +24,17 @@ class _ContactListPageState extends State {
@override
Widget build(final BuildContext context) {
return Scaffold(
- backgroundColor: VidarColors.secondaryMetallicViolet,
+ backgroundColor: Settings.colorSet.secondary,
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
floatingActionButton: DecoratedBox(
decoration: BoxDecoration(
- color: VidarColors.secondaryMetallicViolet,
- border: Border.all(color: Colors.white, width: 2),
+ color: Settings.colorSet.secondary,
+ border: Border.all(color: Settings.colorSet.text, width: 2),
borderRadius: BorderRadius.circular(10),
),
child: FloatingActionButton(
+ elevation: 0,
+ highlightElevation: 0,
onPressed: () {
final Contact newContact = Contact("", "", "");
clearNavigatorAndPush(
@@ -41,7 +43,7 @@ class _ContactListPageState extends State {
);
},
backgroundColor: Colors.transparent,
- foregroundColor: Colors.white,
+ foregroundColor: Settings.colorSet.text,
child: const Icon(Icons.add_comment),
),
),
@@ -59,12 +61,12 @@ class _ContactListPageState extends State {
),
appBar: AppBar(
- backgroundColor: VidarColors.primaryDarkSpaceCadet,
- title: const Text(
+ backgroundColor: Settings.colorSet.primary,
+ title: Text(
"Vidar - For Privacy's Sake",
style: TextStyle(
fontSize: 18,
- color: Colors.white,
+ color: Settings.colorSet.text,
decoration: TextDecoration.none,
),
),
@@ -75,7 +77,7 @@ class _ContactListPageState extends State {
onPressed: () {
clearNavigatorAndPush(context, const SettingsPage());
},
- icon: const Icon(Icons.settings, color: Colors.white),
+ icon: Icon(Icons.settings, color: Settings.colorSet.text),
tooltip: "Settings",
),
),
diff --git a/lib/pages/edit_contact.dart b/lib/pages/edit_contact.dart
index a98fe3f..b8b64be 100644
--- a/lib/pages/edit_contact.dart
+++ b/lib/pages/edit_contact.dart
@@ -187,7 +187,7 @@ class _EditContactPageState extends State {
Widget build(final BuildContext context) {
return Container(
margin: const EdgeInsets.only(top: 30),
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
child: Column(
children: [
Column(
@@ -200,11 +200,11 @@ class _EditContactPageState extends State {
bottom: 30,
),
child: Material(
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
child: Container(
height: 50,
decoration: BoxDecoration(
- color: VidarColors.secondaryMetallicViolet,
+ color: Settings.colorSet.secondary,
borderRadius: BorderRadius.circular(7),
border: Border.all(color: Colors.transparent),
),
@@ -212,13 +212,16 @@ class _EditContactPageState extends State {
child: TextField(
decoration: InputDecoration(
hintText: "Name",
- hintStyle: const TextStyle(color: Colors.white),
+ hintStyle: TextStyle(color: Settings.colorSet.text),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(7),
borderSide: BorderSide.none,
),
),
- style: const TextStyle(color: Colors.white, fontSize: 12),
+ style: TextStyle(
+ color: Settings.colorSet.text,
+ fontSize: 12,
+ ),
onChanged: (final String value) {
newName = value;
},
@@ -241,11 +244,11 @@ class _EditContactPageState extends State {
160, // -100 for margins, -50 for button and -10 for button margin
height: 50,
child: Material(
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
child: Container(
height: 50,
decoration: BoxDecoration(
- color: VidarColors.secondaryMetallicViolet,
+ color: Settings.colorSet.secondary,
borderRadius: BorderRadius.circular(7),
border: Border.all(color: Colors.transparent),
),
@@ -255,8 +258,8 @@ class _EditContactPageState extends State {
decoration: InputDecoration(
hintText:
"Encryption Key${Settings.allowUnencryptedMessages ? ", 0=No Key" : ""}",
- hintStyle: const TextStyle(
- color: Colors.white,
+ hintStyle: TextStyle(
+ color: Settings.colorSet.text,
fontSize: 12,
),
border: OutlineInputBorder(
@@ -264,7 +267,7 @@ class _EditContactPageState extends State {
borderSide: BorderSide.none,
),
),
- style: const TextStyle(color: Colors.white),
+ style: TextStyle(color: Settings.colorSet.text),
onChanged: (final String value) {
newKey = value;
},
@@ -283,15 +286,14 @@ class _EditContactPageState extends State {
encryptionKeyController.text = newKey ?? "";
},
style: IconButton.styleFrom(
- backgroundColor:
- VidarColors.secondaryMetallicViolet,
+ backgroundColor: Settings.colorSet.secondary,
shape: RoundedRectangleBorder(
borderRadius: BorderRadiusGeometry.circular(7),
),
),
- icon: const Icon(
+ icon: Icon(
Icons.change_circle_outlined,
- color: Colors.white,
+ color: Settings.colorSet.text,
),
),
),
@@ -308,11 +310,11 @@ class _EditContactPageState extends State {
bottom: 30,
),
child: Material(
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
child: Container(
height: 50,
decoration: BoxDecoration(
- color: VidarColors.secondaryMetallicViolet,
+ color: Settings.colorSet.secondary,
borderRadius: BorderRadius.circular(7),
border: Border.all(color: Colors.transparent),
),
@@ -320,13 +322,16 @@ class _EditContactPageState extends State {
child: TextField(
decoration: InputDecoration(
hintText: "Phone Number (international)",
- hintStyle: const TextStyle(color: Colors.white),
+ hintStyle: TextStyle(color: Settings.colorSet.text),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(7),
borderSide: BorderSide.none,
),
),
- style: const TextStyle(color: Colors.white, fontSize: 12),
+ style: TextStyle(
+ color: Settings.colorSet.text,
+ fontSize: 12,
+ ),
onChanged: (final String value) {
newPhoneNumber = value;
},
@@ -343,14 +348,14 @@ class _EditContactPageState extends State {
children: [
BasicButton(
buttonText: "Discard",
- textColor: Colors.white,
- buttonColor: VidarColors.secondaryMetallicViolet,
+ textColor: Settings.colorSet.text,
+ buttonColor: Settings.colorSet.secondary,
onPressed: discard,
),
BasicButton(
buttonText: "Save",
- textColor: Colors.white,
- buttonColor: VidarColors.tertiaryGold,
+ textColor: Settings.colorSet.text,
+ buttonColor: Settings.colorSet.tertiary,
onPressed: save,
),
],
diff --git a/lib/pages/no_sms_permission.dart b/lib/pages/no_sms_permission.dart
index a6c4e8e..2761be2 100644
--- a/lib/pages/no_sms_permission.dart
+++ b/lib/pages/no_sms_permission.dart
@@ -1,5 +1,5 @@
import "package:flutter/material.dart";
-import "package:vidar/configuration.dart";
+import "package:vidar/utils/settings.dart";
class NoSmsPermissionPage extends StatelessWidget {
const NoSmsPermissionPage({super.key});
@@ -7,14 +7,14 @@ class NoSmsPermissionPage extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return ColoredBox(
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
child: Center(
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.8,
- child: const Text(
+ child: Text(
"To use Vidar you need to enable SMS permissions. Enable SMS permissions in the app settings then restart the app.",
style: TextStyle(
- color: Colors.white,
+ color: Settings.colorSet.text,
fontSize: 20,
decoration: TextDecoration.none,
),
diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart
index 058de09..0078e4d 100644
--- a/lib/pages/settings_page.dart
+++ b/lib/pages/settings_page.dart
@@ -3,12 +3,14 @@ import "package:logging/logging.dart";
import "package:permission_handler/permission_handler.dart";
import "package:vidar/configuration.dart";
import "package:vidar/pages/contact_list.dart";
+import "package:vidar/utils/colors.dart";
import "package:vidar/utils/common_object.dart";
import "package:vidar/utils/log.dart";
import "package:vidar/utils/settings.dart";
import "package:vidar/utils/storage.dart";
import "package:vidar/widgets/boolean_setting.dart";
import "package:vidar/widgets/buttons.dart";
+import "package:vidar/widgets/color_set_select.dart";
class SettingsPage extends StatefulWidget {
const SettingsPage({super.key});
@@ -30,6 +32,15 @@ class _SettingsPageState extends State {
settingText: "Keep Logs",
);
+ BooleanSetting showMessageBarHints = BooleanSetting(
+ setting: Settings.showMessageBarHints,
+ settingText: "Show message bar hints",
+ );
+
+ ColorSetSelect colorSetSelect = ColorSetSelect(
+ selectedSet: Settings.colorSet.colorSetName,
+ );
+
@override
void initState() {
super.initState();
@@ -83,6 +94,8 @@ class _SettingsPageState extends State {
}
CommonObject.logs = [];
}
+ Settings.showMessageBarHints = showMessageBarHints.setting;
+ Settings.colorSet = getColorSetFromName(colorSetSelect.selectedSet);
if (mounted) {
saveSettings(CommonObject.settings, context: context);
@@ -107,14 +120,21 @@ class _SettingsPageState extends State {
@override
Widget build(final BuildContext context) {
return ColoredBox(
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
spacing: 60,
children: [
- Column(children: [allowUnencryptedMessages, keepLogs]),
+ Column(
+ children: [
+ allowUnencryptedMessages,
+ keepLogs,
+ showMessageBarHints,
+ colorSetSelect,
+ ],
+ ),
Container(
margin: const EdgeInsets.only(top: 60),
child: Row(
@@ -122,14 +142,14 @@ class _SettingsPageState extends State {
children: [
BasicButton(
buttonText: "Discard",
- textColor: Colors.white,
- buttonColor: VidarColors.secondaryMetallicViolet,
+ textColor: Settings.colorSet.text,
+ buttonColor: Settings.colorSet.secondary,
onPressed: _discard,
),
BasicButton(
buttonText: "Save",
- textColor: Colors.white,
- buttonColor: VidarColors.tertiaryGold,
+ textColor: Settings.colorSet.text,
+ buttonColor: Settings.colorSet.tertiary,
onPressed: _save,
),
],
@@ -141,8 +161,8 @@ class _SettingsPageState extends State {
padding: const EdgeInsets.only(bottom: 150),
child: BasicButton(
buttonText: "Wipe Keys",
- textColor: Colors.white,
- buttonColor: VidarColors.extraFireBrick,
+ textColor: Settings.colorSet.text,
+ buttonColor: Settings.colorSet.wipeKeyButton,
width: 200,
onPressed: () {
showDialog(
diff --git a/lib/utils/colors.dart b/lib/utils/colors.dart
new file mode 100644
index 0000000..dccdf11
--- /dev/null
+++ b/lib/utils/colors.dart
@@ -0,0 +1,128 @@
+import "package:flutter/material.dart";
+
+class ColorSet {
+ late final String colorSetName;
+ late final Color primary;
+ late final Color secondary;
+ late final Color tertiary;
+ late final Color wipeKeyButton;
+ late final Color text;
+ late final Color inactiveTrack;
+ late final Color? dropdownFocus;
+ late final Color? sendButton;
+}
+
+const List availableColorSets = [
+ "Default",
+ "Playa",
+ "Monochrome",
+ "Bubbly",
+];
+
+class VidarColorSet extends ColorSet {
+ VidarColorSet() {
+ colorSetName = "Default";
+
+ /// #1a1c28
+ primary = const Color.fromARGB(255, 26, 28, 40);
+
+ /// #64007b
+ secondary = const Color.fromARGB(255, 53, 22, 100);
+
+ /// #b18c19
+ tertiary = const Color.fromARGB(255, 177, 140, 25);
+
+ /// #140627
+ inactiveTrack = const Color.fromARGB(255, 20, 6, 39);
+
+ /// #b22222
+ wipeKeyButton = const Color.fromARGB(255, 178, 34, 34);
+
+ text = Colors.white;
+
+ dropdownFocus = null;
+ sendButton = null;
+ }
+}
+
+class PlayaColorSet extends ColorSet {
+ PlayaColorSet() {
+ colorSetName = "Playa";
+
+ /// #FFFA8D
+ primary = const Color.fromARGB(255, 255, 250, 141);
+
+ /// #A8F1FF
+ secondary = const Color.fromARGB(255, 168, 241, 255);
+
+ /// 4ED7F1
+ tertiary = const Color.fromARGB(255, 78, 215, 241);
+
+ /// #FADA7A
+ inactiveTrack = const Color.fromARGB(255, 250, 218, 122);
+
+ /// #FF7D29
+ wipeKeyButton = const Color.fromARGB(255, 255, 125, 41);
+
+ /// #F2F6D0
+ text = const Color.fromARGB(255, 28, 60, 103);
+
+ dropdownFocus = null;
+ sendButton = null;
+ }
+}
+
+class MonochromeColorSet extends ColorSet {
+ MonochromeColorSet() {
+ colorSetName = "Monochrome";
+ primary = const Color.fromARGB(255, 30, 30, 30);
+ secondary = Colors.black;
+ tertiary = const Color.fromARGB(255, 83, 83, 83);
+ inactiveTrack = const Color.fromARGB(255, 111, 111, 111);
+ wipeKeyButton = const Color.fromARGB(255, 200, 200, 200);
+ text = Colors.white;
+ dropdownFocus = null;
+ sendButton = null;
+ }
+}
+
+class BubblyColorSet extends ColorSet {
+ BubblyColorSet() {
+ colorSetName = "Bubbly";
+
+ /// #084b83
+ primary = const Color.fromARGB(255, 8, 75, 131);
+
+ /// #ff66b3
+ secondary = const Color.fromARGB(255, 255, 102, 179);
+
+ /// #022d40
+ tertiary = const Color.fromARGB(255, 2, 45, 64);
+
+ /// #42bfdd
+ inactiveTrack = const Color.fromARGB(255, 66, 191, 221);
+
+ /// #a528ff
+ wipeKeyButton = const Color.fromARGB(255, 165, 40, 255);
+
+ /// #f0f6f6
+ text = const Color.fromARGB(255, 240, 246, 246);
+
+ dropdownFocus = wipeKeyButton;
+ sendButton = primary;
+ }
+}
+
+/// If color set is not found then it returns default
+ColorSet getColorSetFromName(final String colorSetName) {
+ switch (colorSetName.toLowerCase()) {
+ case "playa":
+ return PlayaColorSet();
+ case "monochrome":
+ return MonochromeColorSet();
+ case "bubbly":
+ return BubblyColorSet();
+ default:
+ return VidarColorSet();
+ }
+}
diff --git a/lib/utils/settings.dart b/lib/utils/settings.dart
index ede2ddd..a150a0c 100644
--- a/lib/utils/settings.dart
+++ b/lib/utils/settings.dart
@@ -1,3 +1,4 @@
+import "package:vidar/utils/colors.dart";
import "package:vidar/utils/common_object.dart";
/// Static class for storing the active user settings of the program.
@@ -7,11 +8,17 @@ class Settings {
static bool keepLogs = false;
+ static ColorSet colorSet = VidarColorSet();
+
+ static bool showMessageBarHints = true;
+
/// Get map of the state of all instance variable of Settings.
Map toMap() {
return {
"allowUnencryptedMessages": allowUnencryptedMessages,
"keepLogs": keepLogs,
+ "showMessageBarHints": showMessageBarHints,
+ "colorSet": colorSet.colorSetName,
};
}
@@ -19,6 +26,9 @@ class Settings {
/// If setting is not found then it goes to the default setting
void fromMap(final Map map) {
keepLogs = map["keepLogs"] as bool? ?? keepLogs;
+ showMessageBarHints =
+ map["showMessageBarHints"] as bool? ?? showMessageBarHints;
+ colorSet = getColorSetFromName(map["colorSet"] as String? ?? "default");
final bool? newAllowUnencryptedMessages =
map["allowUnencryptedMessages"]! as bool?;
diff --git a/lib/widgets/boolean_setting.dart b/lib/widgets/boolean_setting.dart
index 3e4f971..2af5491 100644
--- a/lib/widgets/boolean_setting.dart
+++ b/lib/widgets/boolean_setting.dart
@@ -1,5 +1,6 @@
import "package:flutter/material.dart";
import "package:vidar/configuration.dart";
+import "package:vidar/utils/settings.dart";
// ignore: must_be_immutable
class BooleanSetting extends StatefulWidget {
@@ -31,7 +32,7 @@ class _BooleanSettingState extends State {
Widget build(final BuildContext context) {
return Container(
margin: const EdgeInsets.only(top: 40),
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@@ -42,14 +43,14 @@ class _BooleanSettingState extends State {
child: Material(
color: Colors.transparent,
child: Switch(
- activeColor: VidarColors.tertiaryGold,
- inactiveThumbColor: VidarColors.secondaryMetallicViolet,
- inactiveTrackColor: VidarColors.extraMidnightPurple,
+ activeColor: Settings.colorSet.tertiary,
+ inactiveThumbColor: Settings.colorSet.secondary,
+ inactiveTrackColor: Settings.colorSet.inactiveTrack,
trackOutlineColor: WidgetStateProperty.resolveWith(
(final Set states) =>
states.contains(WidgetState.selected)
? null
- : VidarColors.secondaryMetallicViolet,
+ : Settings.colorSet.secondary,
),
value: widget.setting,
onChanged: (final bool value) {
@@ -65,8 +66,8 @@ class _BooleanSettingState extends State {
width: MediaQuery.of(context).size.width * 0.6,
child: Text(
settingText,
- style: const TextStyle(
- color: Colors.white,
+ style: TextStyle(
+ color: Settings.colorSet.text,
fontSize: SizeConfiguration.settingInfoText,
decoration: TextDecoration.none,
),
diff --git a/lib/widgets/color_set_select.dart b/lib/widgets/color_set_select.dart
new file mode 100644
index 0000000..a4636a5
--- /dev/null
+++ b/lib/widgets/color_set_select.dart
@@ -0,0 +1,75 @@
+import "package:flutter/material.dart";
+import "package:vidar/utils/colors.dart";
+import "package:vidar/utils/settings.dart";
+
+// ignore: must_be_immutable
+class ColorSetSelect extends StatefulWidget {
+ ColorSetSelect({required this.selectedSet, super.key});
+
+ String selectedSet;
+
+ @override
+ _ColorSetSelectState createState() => _ColorSetSelectState();
+}
+
+class _ColorSetSelectState extends State {
+ _ColorSetSelectState();
+
+ late final String settingText;
+
+ @override
+ Widget build(final BuildContext context) {
+ return Container(
+ margin: const EdgeInsets.only(top: 40),
+ color: Settings.colorSet.primary,
+ child: Material(
+ color: Colors.transparent,
+ child: SizedBox(
+ width: MediaQuery.of(context).size.width * 0.7,
+ child: DecoratedBox(
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(10.0),
+ color: Settings.colorSet.secondary,
+ ),
+ child: DropdownButtonHideUnderline(
+ child: DropdownButton(
+ isExpanded: true,
+ borderRadius: BorderRadius.circular(10.0),
+ padding: EdgeInsets.only(
+ left: MediaQuery.of(context).size.width * 0.1,
+ right: MediaQuery.of(context).size.width * 0.05,
+ ),
+ dropdownColor: Settings.colorSet.secondary,
+ focusColor:
+ Settings.colorSet.dropdownFocus ??
+ Settings.colorSet.tertiary,
+ icon: Icon(
+ Icons.arrow_circle_down_sharp,
+ color: Settings.colorSet.text,
+ ),
+
+ style: TextStyle(color: Settings.colorSet.text),
+ value: widget.selectedSet,
+ items: availableColorSets
+ .map>(
+ (final String value) => DropdownMenuItem(
+ value: value,
+ child: Text(value),
+ ),
+ )
+ .toList(),
+ onChanged: (final String? value) {
+ if (value != null) {
+ setState(() {
+ widget.selectedSet = value;
+ });
+ }
+ },
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/widgets/contact_badge.dart b/lib/widgets/contact_badge.dart
index 550cbff..5b59a00 100644
--- a/lib/widgets/contact_badge.dart
+++ b/lib/widgets/contact_badge.dart
@@ -21,7 +21,7 @@ class ContactBadge extends StatelessWidget {
padding: const EdgeInsets.only(top: 10, bottom: 10),
margin: const EdgeInsets.only(top: 5, bottom: 5, left: 10, right: 10),
decoration: BoxDecoration(
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
borderRadius: BorderRadius.circular(10),
),
@@ -29,17 +29,17 @@ class ContactBadge extends StatelessWidget {
children: [
Text(
contact.name,
- style: const TextStyle(
+ style: TextStyle(
fontSize: 32,
- color: Colors.white,
+ color: Settings.colorSet.text,
decoration: TextDecoration.none,
),
),
Text(
contact.phoneNumber,
- style: const TextStyle(
+ style: TextStyle(
fontSize: 12,
- color: Colors.white,
+ color: Settings.colorSet.text,
decoration: TextDecoration.none,
),
),
diff --git a/lib/widgets/conversation_widget.dart b/lib/widgets/conversation_widget.dart
index a7eb836..0ee4909 100644
--- a/lib/widgets/conversation_widget.dart
+++ b/lib/widgets/conversation_widget.dart
@@ -63,16 +63,16 @@ class _ConversationWidgetState extends State {
);
}
return ColoredBox(
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
child: Center(
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.6,
- child: const Center(
+ child: Center(
child: Text(
"SMS query failed, please ensure the phone number is correct.",
style: TextStyle(
fontSize: 20,
- color: Colors.white,
+ color: Settings.colorSet.text,
),
),
),
@@ -135,7 +135,7 @@ class _ConversationWidgetState extends State {
);
}
return ColoredBox(
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
child: ListView(
reverse: true,
children: decryptedSpeechBubbles,
diff --git a/lib/widgets/loading_screen.dart b/lib/widgets/loading_screen.dart
index 9da8fbd..6b85e40 100644
--- a/lib/widgets/loading_screen.dart
+++ b/lib/widgets/loading_screen.dart
@@ -2,6 +2,7 @@
import "package:flutter/material.dart";
import "package:vidar/configuration.dart";
+import "package:vidar/utils/settings.dart";
import "package:vidar/widgets/loading_text.dart";
class ChatLoadingScreen extends LoadingScreen {
@@ -25,7 +26,7 @@ class LoadingScreen extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return ColoredBox(
- color: VidarColors.primaryDarkSpaceCadet,
+ color: Settings.colorSet.primary,
child: Column(
spacing: 30,
mainAxisAlignment: MainAxisAlignment.center,
@@ -33,13 +34,13 @@ class LoadingScreen extends StatelessWidget {
Transform.scale(
scale: 2,
child: CircularProgressIndicator(
- color: VidarColors.secondaryMetallicViolet,
+ color: Settings.colorSet.secondary,
),
),
DecryptingText(
targets: loadingMessages,
style: TextStyle(
- color: VidarColors.secondaryMetallicViolet,
+ color: Settings.colorSet.secondary,
fontSize: SizeConfiguration.loadingFontSize,
),
),
diff --git a/lib/widgets/message_bar.dart b/lib/widgets/message_bar.dart
index f8c8627..20dd1f8 100644
--- a/lib/widgets/message_bar.dart
+++ b/lib/widgets/message_bar.dart
@@ -1,3 +1,5 @@
+import "dart:math";
+
import "package:flutter/material.dart";
import "package:vidar/configuration.dart";
import "package:vidar/utils/common_object.dart";
@@ -41,7 +43,7 @@ class _MessageBarState extends State {
final String text,
) {
return Container(
- color: VidarColors.tertiaryGold,
+ color: Settings.colorSet.tertiary,
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom > 50
? MediaQuery.of(context).viewInsets.bottom
@@ -57,8 +59,8 @@ class _MessageBarState extends State {
width: MediaQuery.of(context).size.width * 0.75,
child: Text(
text,
- style: const TextStyle(
- color: VidarColors.secondaryMetallicViolet,
+ style: TextStyle(
+ color: Settings.colorSet.secondary,
fontWeight: FontWeight.bold,
fontSize: 16,
),
@@ -69,10 +71,7 @@ class _MessageBarState extends State {
error = false;
errorNotifier.notifyListeners();
},
- icon: const Icon(
- Icons.sms,
- color: VidarColors.secondaryMetallicViolet,
- ),
+ icon: Icon(Icons.sms, color: Settings.colorSet.secondary),
),
],
),
@@ -114,86 +113,101 @@ class _MessageBarState extends State {
}
} else {
return Container(
- color: VidarColors.tertiaryGold,
+ color: Settings.colorSet.secondary,
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom > 50
? MediaQuery.of(context).viewInsets.bottom
: 50,
),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: [
- Container(
- decoration: BoxDecoration(
- color: VidarColors.secondaryMetallicViolet,
- borderRadius: BorderRadius.circular(4),
- ),
- padding: const EdgeInsets.only(left: 10),
- width:
- MediaQuery.sizeOf(context).width -
- SizeConfiguration.sendMessageIconSize * 2.5,
- child: TextField(
- controller: controller,
- style: const TextStyle(color: Colors.white),
- decoration: InputDecoration(
- border: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: BorderSide.none,
+ child: Padding(
+ padding: const EdgeInsets.only(top: 5.0),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ Container(
+ decoration: BoxDecoration(
+ color: Settings.colorSet.primary,
+ borderRadius: BorderRadius.circular(4.0),
+ ),
+ padding: const EdgeInsets.only(left: 10.0),
+ width:
+ MediaQuery.sizeOf(context).width -
+ SizeConfiguration.sendMessageIconSize * 2.5,
+ child: TextField(
+ controller: controller,
+ style: TextStyle(color: Settings.colorSet.text),
+ decoration: InputDecoration(
+ hintText: () {
+ if (Settings.showMessageBarHints) {
+ return MiscellaneousConfiguration
+ .messageHints[Random().nextInt(
+ MiscellaneousConfiguration.messageHints.length,
+ )];
+ } else {
+ return null;
+ }
+ }(),
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10.0),
+ borderSide: BorderSide.none,
+ ),
),
+ onChanged: (final String value) => message = value,
),
- onChanged: (final String value) => message = value,
),
- ),
- SizedBox(
- width: 50,
- height: 60,
- child: Center(
- child: IconButton(
- onPressed: () async {
- final String encryptedMessage = await encryptMessage(
- message,
- contact.encryptionKey,
- );
- if (encryptedMessage.startsWith(
- MiscellaneousConfiguration.errorPrefix,
- )) {
- errorMessage = encryptedMessage.replaceFirst(
- MiscellaneousConfiguration.errorPrefix,
- "",
+ SizedBox(
+ width: 50.0,
+ height: 60.0,
+ child: Center(
+ child: IconButton(
+ onPressed: () async {
+ final String encryptedMessage = await encryptMessage(
+ message,
+ contact.encryptionKey,
);
- error = true;
- errorNotifier.notifyListeners();
- } else {
- sendSms(encryptedMessage, contact.phoneNumber);
- controller.text =
- ""; // Clear only after successful send
- if (CommonObject.currentConversation != null) {
- int delay =
- (encryptedMessage.length ~/ 65) *
- TimeConfiguration.smsUpdateDelay;
- delay = delay == 0 ? 1 : delay;
- Future.delayed(Duration(seconds: delay)).then(
- (_) {
+ if (encryptedMessage.startsWith(
+ MiscellaneousConfiguration.errorPrefix,
+ )) {
+ errorMessage = encryptedMessage.replaceFirst(
+ MiscellaneousConfiguration.errorPrefix,
+ "",
+ );
+ error = true;
+ errorNotifier.notifyListeners();
+ } else {
+ sendSms(encryptedMessage, contact.phoneNumber);
+ controller.text =
+ ""; // Clear only after successful send
+ if (CommonObject.currentConversation != null) {
+ int delay =
+ (encryptedMessage.length ~/ 65) *
+ TimeConfiguration.smsUpdateDelay;
+ delay = delay == 0 ? 1 : delay;
+ Future.delayed(
+ Duration(seconds: delay),
+ ).then((_) {
CommonObject.currentConversation!
.notifyListeners();
- },
- );
- } else if (Settings.keepLogs) {
- CommonObject.logger!.info(
- "Current conversation is null, can not notifyListeners",
- );
+ });
+ } else if (Settings.keepLogs) {
+ CommonObject.logger!.info(
+ "Current conversation is null, can not notifyListeners",
+ );
+ }
}
- }
- },
- icon: const Icon(
- size: SizeConfiguration.sendMessageIconSize,
- Icons.send,
- color: VidarColors.secondaryMetallicViolet,
+ },
+ icon: Icon(
+ size: SizeConfiguration.sendMessageIconSize,
+ Icons.send,
+ color:
+ Settings.colorSet.sendButton ??
+ Settings.colorSet.text,
+ ),
),
),
),
- ),
- ],
+ ],
+ ),
),
);
}
diff --git a/lib/widgets/speech_bubble.dart b/lib/widgets/speech_bubble.dart
index baeb088..4263ba9 100644
--- a/lib/widgets/speech_bubble.dart
+++ b/lib/widgets/speech_bubble.dart
@@ -1,5 +1,6 @@
import "package:flutter/material.dart";
import "package:vidar/configuration.dart";
+import "package:vidar/utils/settings.dart";
import "package:vidar/utils/sms.dart";
class SpeechBubble extends StatelessWidget {
@@ -34,8 +35,8 @@ class SpeechBubble extends StatelessWidget {
),
decoration: BoxDecoration(
color: isMe
- ? VidarColors.secondaryMetallicViolet
- : VidarColors.tertiaryGold,
+ ? Settings.colorSet.secondary
+ : Settings.colorSet.tertiary,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(10),
topRight: const Radius.circular(10),
@@ -45,7 +46,7 @@ class SpeechBubble extends StatelessWidget {
),
child: Text(
message.body,
- style: const TextStyle(color: Colors.white, fontSize: 12),
+ style: TextStyle(color: Settings.colorSet.text, fontSize: 12),
),
),
),
From 1a336aaea631f39e64b88e62519036bc3ac796a9 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 00:01:53 +0200
Subject: [PATCH 04/23] Fixed bug where it would save new contact before
validating that it was valid and successfully added. Before it saved all
contacts excluding the current one.
---
lib/pages/edit_contact.dart | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/lib/pages/edit_contact.dart b/lib/pages/edit_contact.dart
index b8b64be..7ce414c 100644
--- a/lib/pages/edit_contact.dart
+++ b/lib/pages/edit_contact.dart
@@ -87,8 +87,6 @@ class _EditContactPageState extends State {
newPhoneNumber = contact.phoneNumber;
}
- saveData(CommonObject.contactList, CommonObject.settings);
-
switch (caller) {
case ContactPageCaller.chatPage:
if (isInvalidContactByParams(newName, newKey, newPhoneNumber)) {
@@ -118,6 +116,7 @@ class _EditContactPageState extends State {
contact.name = newName!;
contact.encryptionKey = newKey!;
contact.phoneNumber = newPhoneNumber!;
+ saveData(CommonObject.contactList, CommonObject.settings);
clearNavigatorAndPush(context, ChatPage(contact));
}
@@ -152,9 +151,14 @@ class _EditContactPageState extends State {
if (Settings.keepLogs) {
if (success) {
if (LoggingConfiguration.extraVerboseLogs) {
+ contact.name = newName!;
+ contact.encryptionKey = newKey!;
+ contact.phoneNumber = newPhoneNumber!;
+ saveData(CommonObject.contactList, CommonObject.settings);
CommonObject.logger!.info(
"New contact ${contact.uuid} has been saved",
);
+ clearNavigatorAndPush(context, const ContactListPage());
}
} else {
CommonObject.logger!.warning(
@@ -177,6 +181,7 @@ class _EditContactPageState extends State {
contact.name = newName!;
contact.encryptionKey = newKey!;
contact.phoneNumber = newPhoneNumber!;
+ saveData(CommonObject.contactList, CommonObject.settings);
clearNavigatorAndPush(context, const ContactListPage());
}
}
From f7c8f78eac044fb0e6e51a80660fa16c99bf8582 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 01:44:17 +0200
Subject: [PATCH 05/23] Added ability to control font weight for basic button +
made save buttons bold.
---
lib/pages/edit_contact.dart | 1 +
lib/pages/settings_page.dart | 1 +
lib/widgets/buttons.dart | 4 +++-
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/pages/edit_contact.dart b/lib/pages/edit_contact.dart
index 7ce414c..b2d6bfe 100644
--- a/lib/pages/edit_contact.dart
+++ b/lib/pages/edit_contact.dart
@@ -362,6 +362,7 @@ class _EditContactPageState extends State {
textColor: Settings.colorSet.text,
buttonColor: Settings.colorSet.tertiary,
onPressed: save,
+ fontWeight: FontWeight.bold,
),
],
),
diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart
index 0078e4d..d872afc 100644
--- a/lib/pages/settings_page.dart
+++ b/lib/pages/settings_page.dart
@@ -151,6 +151,7 @@ class _SettingsPageState extends State {
textColor: Settings.colorSet.text,
buttonColor: Settings.colorSet.tertiary,
onPressed: _save,
+ fontWeight: FontWeight.bold,
),
],
),
diff --git a/lib/widgets/buttons.dart b/lib/widgets/buttons.dart
index e49316b..22b00e6 100644
--- a/lib/widgets/buttons.dart
+++ b/lib/widgets/buttons.dart
@@ -8,6 +8,7 @@ class BasicButton extends StatelessWidget {
required this.onPressed,
this.width = 100,
this.height = 50,
+ this.fontWeight = FontWeight.normal,
super.key,
});
final Color textColor;
@@ -16,6 +17,7 @@ class BasicButton extends StatelessWidget {
final VoidCallback onPressed;
final double width;
final double height;
+ final FontWeight fontWeight;
@override
Widget build(final BuildContext context) {
@@ -31,7 +33,7 @@ class BasicButton extends StatelessWidget {
),
child: Text(
buttonText,
- style: TextStyle(fontSize: 24, color: textColor),
+ style: TextStyle(fontSize: 24, color: textColor, fontWeight: fontWeight),
),
),
);
From 7c8b6a27091b0fcbcef068cbdcfd49f73d7b81bc Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 01:55:59 +0200
Subject: [PATCH 06/23] Rewrote colorsets, instead of inheriting from colorset,
the different color sets are instances of color set.
---
lib/pages/contact_list.dart | 2 +-
lib/pages/settings_page.dart | 4 +-
lib/utils/colors.dart | 205 +++++++++++++-----------------
lib/utils/settings.dart | 4 +-
lib/widgets/buttons.dart | 6 +-
lib/widgets/color_set_select.dart | 4 +-
lib/widgets/message_bar.dart | 11 +-
7 files changed, 108 insertions(+), 128 deletions(-)
diff --git a/lib/pages/contact_list.dart b/lib/pages/contact_list.dart
index d952988..db2802e 100644
--- a/lib/pages/contact_list.dart
+++ b/lib/pages/contact_list.dart
@@ -28,7 +28,7 @@ class _ContactListPageState extends State {
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
floatingActionButton: DecoratedBox(
decoration: BoxDecoration(
- color: Settings.colorSet.secondary,
+ color: Settings.colorSet.floatingActionButton,
border: Border.all(color: Settings.colorSet.text, width: 2),
borderRadius: BorderRadius.circular(10),
),
diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart
index d872afc..f488080 100644
--- a/lib/pages/settings_page.dart
+++ b/lib/pages/settings_page.dart
@@ -38,7 +38,7 @@ class _SettingsPageState extends State {
);
ColorSetSelect colorSetSelect = ColorSetSelect(
- selectedSet: Settings.colorSet.colorSetName,
+ selectedSet: Settings.colorSet.name,
);
@override
@@ -162,7 +162,7 @@ class _SettingsPageState extends State {
padding: const EdgeInsets.only(bottom: 150),
child: BasicButton(
buttonText: "Wipe Keys",
- textColor: Settings.colorSet.text,
+ textColor: Settings.colorSet.wipeKeyButtonText,
buttonColor: Settings.colorSet.wipeKeyButton,
width: 200,
onPressed: () {
diff --git a/lib/utils/colors.dart b/lib/utils/colors.dart
index dccdf11..382fbe5 100644
--- a/lib/utils/colors.dart
+++ b/lib/utils/colors.dart
@@ -1,128 +1,105 @@
import "package:flutter/material.dart";
class ColorSet {
- late final String colorSetName;
- late final Color primary;
- late final Color secondary;
- late final Color tertiary;
+ ColorSet({
+ required this.name,
+ required this.primary,
+ required this.secondary,
+ required this.tertiary,
+ required this.text,
+ final Color? pWipeKeyButton,
+ final Color? pInactiveTrack,
+ final Color? pDropdownFocus,
+ final Color? pSendButton,
+ final Color? pFloatingActionButton,
+ final Color? pWipeKeyButtonText,
+ final Color? pMessageBarHintText,
+ }) {
+ wipeKeyButton = pWipeKeyButton ?? secondary;
+ inactiveTrack = pInactiveTrack ?? primary;
+ dropdownFocus = pDropdownFocus ?? tertiary;
+ sendButton = pSendButton ?? primary;
+ floatingActionButton = pFloatingActionButton ?? tertiary;
+ wipeKeyButtonText = pWipeKeyButtonText ?? text;
+ messageBarHintText = pMessageBarHintText ?? text;
+ }
+ final String name;
+ final Color primary;
+ final Color secondary;
+ final Color tertiary;
+ final Color text;
+
late final Color wipeKeyButton;
- late final Color text;
late final Color inactiveTrack;
- late final Color? dropdownFocus;
- late final Color? sendButton;
+ late final Color dropdownFocus;
+ late final Color sendButton;
+ late final Color floatingActionButton;
+ late final Color wipeKeyButtonText;
+ late final Color messageBarHintText;
}
-const List availableColorSets = [
- "Default",
- "Playa",
- "Monochrome",
- "Bubbly",
+final List availableColorSets = [
+ vidarColorSet.name,
+ playaColorSet.name,
+ monochromeColorSet.name,
+ bubblyColorSet.name,
];
-class VidarColorSet extends ColorSet {
- VidarColorSet() {
- colorSetName = "Default";
-
- /// #1a1c28
- primary = const Color.fromARGB(255, 26, 28, 40);
-
- /// #64007b
- secondary = const Color.fromARGB(255, 53, 22, 100);
-
- /// #b18c19
- tertiary = const Color.fromARGB(255, 177, 140, 25);
-
- /// #140627
- inactiveTrack = const Color.fromARGB(255, 20, 6, 39);
-
- /// #b22222
- wipeKeyButton = const Color.fromARGB(255, 178, 34, 34);
-
- text = Colors.white;
-
- dropdownFocus = null;
- sendButton = null;
- }
-}
-
-class PlayaColorSet extends ColorSet {
- PlayaColorSet() {
- colorSetName = "Playa";
-
- /// #FFFA8D
- primary = const Color.fromARGB(255, 255, 250, 141);
-
- /// #A8F1FF
- secondary = const Color.fromARGB(255, 168, 241, 255);
-
- /// 4ED7F1
- tertiary = const Color.fromARGB(255, 78, 215, 241);
-
- /// #FADA7A
- inactiveTrack = const Color.fromARGB(255, 250, 218, 122);
-
- /// #FF7D29
- wipeKeyButton = const Color.fromARGB(255, 255, 125, 41);
-
- /// #F2F6D0
- text = const Color.fromARGB(255, 28, 60, 103);
-
- dropdownFocus = null;
- sendButton = null;
- }
-}
-
-class MonochromeColorSet extends ColorSet {
- MonochromeColorSet() {
- colorSetName = "Monochrome";
- primary = const Color.fromARGB(255, 30, 30, 30);
- secondary = Colors.black;
- tertiary = const Color.fromARGB(255, 83, 83, 83);
- inactiveTrack = const Color.fromARGB(255, 111, 111, 111);
- wipeKeyButton = const Color.fromARGB(255, 200, 200, 200);
- text = Colors.white;
- dropdownFocus = null;
- sendButton = null;
- }
-}
-
-class BubblyColorSet extends ColorSet {
- BubblyColorSet() {
- colorSetName = "Bubbly";
-
- /// #084b83
- primary = const Color.fromARGB(255, 8, 75, 131);
-
- /// #ff66b3
- secondary = const Color.fromARGB(255, 255, 102, 179);
-
- /// #022d40
- tertiary = const Color.fromARGB(255, 2, 45, 64);
-
- /// #42bfdd
- inactiveTrack = const Color.fromARGB(255, 66, 191, 221);
-
- /// #a528ff
- wipeKeyButton = const Color.fromARGB(255, 165, 40, 255);
-
- /// #f0f6f6
- text = const Color.fromARGB(255, 240, 246, 246);
-
- dropdownFocus = wipeKeyButton;
- sendButton = primary;
- }
-}
+final ColorSet vidarColorSet = ColorSet(
+ name: "Default",
+ primary: const Color.fromARGB(255, 26, 28, 40),
+ secondary: const Color.fromARGB(255, 53, 22, 100),
+ tertiary: const Color.fromARGB(255, 177, 140, 25),
+ text: Colors.white,
+ pWipeKeyButton: const Color.fromARGB(255, 178, 34, 34),
+ pFloatingActionButton: const Color.fromARGB(255, 53, 22, 100),
+ pMessageBarHintText: const Color.fromARGB(255, 103, 40, 198),
+);
+
+final ColorSet playaColorSet = ColorSet(
+ name: "Playa",
+ primary: const Color.fromARGB(255, 255, 250, 141),
+ secondary: const Color.fromARGB(255, 168, 241, 255),
+ tertiary: const Color.fromARGB(255, 78, 215, 241),
+ text: const Color.fromARGB(255, 28, 60, 103),
+ pWipeKeyButton: const Color.fromARGB(255, 255, 125, 41),
+ pInactiveTrack: const Color.fromARGB(255, 250, 218, 122),
+);
+
+final ColorSet monochromeColorSet = ColorSet(
+ name: "Monochrome",
+ primary: const Color.fromARGB(255, 30, 30, 30),
+ secondary: Colors.black,
+ tertiary: const Color.fromARGB(255, 83, 83, 83),
+ text: Colors.white,
+ pWipeKeyButton: const Color.fromARGB(255, 200, 200, 200),
+ pInactiveTrack: const Color.fromARGB(255, 41, 41, 41),
+ pSendButton: const Color.fromARGB(255, 200, 200, 200),
+ pWipeKeyButtonText: Colors.black,
+);
+
+final ColorSet bubblyColorSet = ColorSet(
+ name: "Bubbly",
+ primary: const Color.fromARGB(255, 8, 75, 131),
+ secondary: const Color.fromARGB(255, 255, 102, 179),
+ tertiary: const Color.fromARGB(255, 2, 45, 64),
+ text: const Color.fromARGB(255, 240, 246, 246),
+ pWipeKeyButton: const Color.fromARGB(255, 165, 40, 255),
+ pInactiveTrack: const Color.fromARGB(255, 66, 191, 221),
+ pSendButton: const Color.fromARGB(255, 8, 75, 131),
+ pDropdownFocus: const Color.fromARGB(255, 165, 40, 255),
+ pMessageBarHintText: const Color.fromARGB(255, 66, 191, 221),
+);
/// If color set is not found then it returns default
ColorSet getColorSetFromName(final String colorSetName) {
- switch (colorSetName.toLowerCase()) {
- case "playa":
- return PlayaColorSet();
- case "monochrome":
- return MonochromeColorSet();
- case "bubbly":
- return BubblyColorSet();
- default:
- return VidarColorSet();
+ if (colorSetName == playaColorSet.name) {
+ return playaColorSet;
+ } else if (colorSetName == monochromeColorSet.name) {
+ return monochromeColorSet;
+ } else if (colorSetName == bubblyColorSet.name) {
+ return bubblyColorSet;
+ } else {
+ return vidarColorSet;
}
}
diff --git a/lib/utils/settings.dart b/lib/utils/settings.dart
index a150a0c..86b14a4 100644
--- a/lib/utils/settings.dart
+++ b/lib/utils/settings.dart
@@ -8,7 +8,7 @@ class Settings {
static bool keepLogs = false;
- static ColorSet colorSet = VidarColorSet();
+ static ColorSet colorSet = vidarColorSet;
static bool showMessageBarHints = true;
@@ -18,7 +18,7 @@ class Settings {
"allowUnencryptedMessages": allowUnencryptedMessages,
"keepLogs": keepLogs,
"showMessageBarHints": showMessageBarHints,
- "colorSet": colorSet.colorSetName,
+ "colorSet": colorSet.name,
};
}
diff --git a/lib/widgets/buttons.dart b/lib/widgets/buttons.dart
index 22b00e6..83dd477 100644
--- a/lib/widgets/buttons.dart
+++ b/lib/widgets/buttons.dart
@@ -33,7 +33,11 @@ class BasicButton extends StatelessWidget {
),
child: Text(
buttonText,
- style: TextStyle(fontSize: 24, color: textColor, fontWeight: fontWeight),
+ style: TextStyle(
+ fontSize: 24,
+ color: textColor,
+ fontWeight: fontWeight,
+ ),
),
),
);
diff --git a/lib/widgets/color_set_select.dart b/lib/widgets/color_set_select.dart
index a4636a5..1701721 100644
--- a/lib/widgets/color_set_select.dart
+++ b/lib/widgets/color_set_select.dart
@@ -40,9 +40,7 @@ class _ColorSetSelectState extends State {
right: MediaQuery.of(context).size.width * 0.05,
),
dropdownColor: Settings.colorSet.secondary,
- focusColor:
- Settings.colorSet.dropdownFocus ??
- Settings.colorSet.tertiary,
+ focusColor: Settings.colorSet.dropdownFocus,
icon: Icon(
Icons.arrow_circle_down_sharp,
color: Settings.colorSet.text,
diff --git a/lib/widgets/message_bar.dart b/lib/widgets/message_bar.dart
index 20dd1f8..af8b6ac 100644
--- a/lib/widgets/message_bar.dart
+++ b/lib/widgets/message_bar.dart
@@ -46,7 +46,7 @@ class _MessageBarState extends State {
color: Settings.colorSet.tertiary,
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom > 50
- ? MediaQuery.of(context).viewInsets.bottom
+ ? MediaQuery.of(context).viewInsets.bottom + 10
: 50,
left: 20,
right: 20,
@@ -116,7 +116,7 @@ class _MessageBarState extends State {
color: Settings.colorSet.secondary,
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom > 50
- ? MediaQuery.of(context).viewInsets.bottom
+ ? MediaQuery.of(context).viewInsets.bottom + 10
: 50,
),
child: Padding(
@@ -147,6 +147,9 @@ class _MessageBarState extends State {
return null;
}
}(),
+ hintStyle: TextStyle(
+ color: Settings.colorSet.messageBarHintText,
+ ),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
borderSide: BorderSide.none,
@@ -199,9 +202,7 @@ class _MessageBarState extends State {
icon: Icon(
size: SizeConfiguration.sendMessageIconSize,
Icons.send,
- color:
- Settings.colorSet.sendButton ??
- Settings.colorSet.text,
+ color: Settings.colorSet.sendButton,
),
),
),
From 6b71f84ada9b4e4b174ae4c49878e8f5231752aa Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 02:01:31 +0200
Subject: [PATCH 07/23] Changed keyboard type of phone number field.
---
lib/pages/edit_contact.dart | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/pages/edit_contact.dart b/lib/pages/edit_contact.dart
index b2d6bfe..740acfd 100644
--- a/lib/pages/edit_contact.dart
+++ b/lib/pages/edit_contact.dart
@@ -325,6 +325,7 @@ class _EditContactPageState extends State {
),
padding: const EdgeInsets.only(left: 10),
child: TextField(
+ keyboardType: TextInputType.phone,
decoration: InputDecoration(
hintText: "Phone Number (international)",
hintStyle: TextStyle(color: Settings.colorSet.text),
From ce58482f1f167ccb4718b28444523155de199212 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 15:59:09 +0200
Subject: [PATCH 08/23] Changed navigation in ErrorPopup, now uses
clearNavigatorAndPush
---
lib/widgets/error_popup.dart | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/lib/widgets/error_popup.dart b/lib/widgets/error_popup.dart
index 6c54808..dc5938c 100644
--- a/lib/widgets/error_popup.dart
+++ b/lib/widgets/error_popup.dart
@@ -1,6 +1,7 @@
import "package:flutter/material.dart";
import "package:vidar/pages/contact_list.dart";
import "package:vidar/utils/log.dart";
+import "package:vidar/utils/navigation.dart";
import "package:vidar/utils/settings.dart";
/// Alert dialog template for errors
@@ -36,12 +37,7 @@ class _ErrorPopupState extends State {
final List list = [
TextButton(
onPressed: () {
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (final BuildContext context) => const ContactListPage(),
- ),
- );
+ clearNavigatorAndPush(context, const ContactListPage());
},
child: const Text("Home"),
),
@@ -51,15 +47,9 @@ class _ErrorPopupState extends State {
TextButton(
onPressed: () {
exportLogs();
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (final BuildContext context) =>
- const ContactListPage(),
- ),
- );
+ clearNavigatorAndPush(context, const ContactListPage());
},
- child: const Text("Save logs"),
+ child: const Text("Export logs"),
),
);
}
From 8eb897a9eca87de5edaf9e0834f45f8348003409 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 16:04:01 +0200
Subject: [PATCH 09/23] Changed exportLogs popup to use alertdialog instead of
error popup, errorpopup has non relevant actions.
---
lib/utils/log.dart | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/lib/utils/log.dart b/lib/utils/log.dart
index c3d8eb0..d5ce7f1 100644
--- a/lib/utils/log.dart
+++ b/lib/utils/log.dart
@@ -1,11 +1,12 @@
import "dart:io";
-import "package:flutter/material.dart"
- show BuildContext, debugPrint, showDialog;
+import "package:flutter/material.dart";
import "package:logging/logging.dart";
import "package:permission_handler/permission_handler.dart";
import "package:vidar/configuration.dart";
+import "package:vidar/pages/contact_list.dart";
import "package:vidar/utils/common_object.dart";
+import "package:vidar/utils/navigation.dart";
import "package:vidar/utils/settings.dart";
import "package:vidar/widgets/error_popup.dart";
@@ -65,10 +66,16 @@ Future exportLogs({final BuildContext? context}) async {
if (context != null && context.mounted) {
showDialog(
context: context,
- builder: (final BuildContext context) => ErrorPopup(
- title: "Logs exported",
- body: 'Logs have been exported to "${file.path}"',
- enableReturn: false,
+ builder: (final BuildContext context) => AlertDialog(
+ title: const Text("Logs exported"),
+ content: Text('Logs have been exported to "${file.path}"'),
+ actions: [
+ TextButton(
+ onPressed: () =>
+ clearNavigatorAndPush(context, const ContactListPage()),
+ child: const Text("Dismiss"),
+ ),
+ ],
),
);
}
From 9ae93a9304b2644da57b72c15ee4e7101f639341 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 16:05:33 +0200
Subject: [PATCH 10/23] Added button to export logs in settings (to export logs
when no error occurs)
---
lib/pages/settings_page.dart | 98 ++++++++++++++++++++----------------
lib/utils/colors.dart | 6 ++-
2 files changed, 61 insertions(+), 43 deletions(-)
diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart
index f488080..706c10f 100644
--- a/lib/pages/settings_page.dart
+++ b/lib/pages/settings_page.dart
@@ -121,11 +121,10 @@ class _SettingsPageState extends State {
Widget build(final BuildContext context) {
return ColoredBox(
color: Settings.colorSet.primary,
- child: Column(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ child: ListView(
children: [
Column(
- spacing: 60,
+ spacing: 20,
children: [
Column(
children: [
@@ -159,47 +158,62 @@ class _SettingsPageState extends State {
],
),
Padding(
- padding: const EdgeInsets.only(bottom: 150),
- child: BasicButton(
- buttonText: "Wipe Keys",
- textColor: Settings.colorSet.wipeKeyButtonText,
- buttonColor: Settings.colorSet.wipeKeyButton,
- width: 200,
- onPressed: () {
- showDialog(
- context: context,
- builder: (final BuildContext context) {
- return AlertDialog(
- title: const Text("Wipe all keys"),
- content: const Text(
- "Are you sure you want to wipe all keys? This is a permanent action which can not be undone.",
- ),
- actions: [
- TextButton(
- onPressed: () {
- Navigator.of(context).pop();
- },
- child: const Text("Cancel"),
- ),
- TextButton(
- onPressed: () {
- CommonObject.contactList.wipeKeys();
- wipeSecureStorage();
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (final BuildContext context) =>
- const ContactListPage(),
- ),
- );
- },
- child: const Text("Wipe Keys"),
- ),
- ],
+ padding: const EdgeInsets.only(top: 100),
+ child: Column(
+ spacing: 50,
+ children: [
+ Visibility(
+ visible: Settings.keepLogs,
+ child: BasicButton(
+ buttonText: "Export Logs",
+ textColor: Settings.colorSet.text,
+ buttonColor: Settings.colorSet.exportLogsButton,
+ onPressed: () => exportLogs(context: context),
+ width: 200,
+ ),
+ ),
+ BasicButton(
+ buttonText: "Wipe Keys",
+ textColor: Settings.colorSet.wipeKeyButtonText,
+ buttonColor: Settings.colorSet.wipeKeyButton,
+ width: 200,
+ onPressed: () {
+ showDialog(
+ context: context,
+ builder: (final BuildContext context) {
+ return AlertDialog(
+ title: const Text("Wipe all keys"),
+ content: const Text(
+ "Are you sure you want to wipe all keys? This is a permanent action which can not be undone.",
+ ),
+ actions: [
+ TextButton(
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ child: const Text("Cancel"),
+ ),
+ TextButton(
+ onPressed: () {
+ CommonObject.contactList.wipeKeys();
+ wipeSecureStorage();
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (final BuildContext context) =>
+ const ContactListPage(),
+ ),
+ );
+ },
+ child: const Text("Wipe Keys"),
+ ),
+ ],
+ );
+ },
);
},
- );
- },
+ ),
+ ],
),
),
],
diff --git a/lib/utils/colors.dart b/lib/utils/colors.dart
index 382fbe5..d53cf1a 100644
--- a/lib/utils/colors.dart
+++ b/lib/utils/colors.dart
@@ -14,6 +14,7 @@ class ColorSet {
final Color? pFloatingActionButton,
final Color? pWipeKeyButtonText,
final Color? pMessageBarHintText,
+ final Color? pExportLogsButton,
}) {
wipeKeyButton = pWipeKeyButton ?? secondary;
inactiveTrack = pInactiveTrack ?? primary;
@@ -22,6 +23,7 @@ class ColorSet {
floatingActionButton = pFloatingActionButton ?? tertiary;
wipeKeyButtonText = pWipeKeyButtonText ?? text;
messageBarHintText = pMessageBarHintText ?? text;
+ exportLogsButton = pExportLogsButton ?? tertiary;
}
final String name;
final Color primary;
@@ -36,6 +38,7 @@ class ColorSet {
late final Color floatingActionButton;
late final Color wipeKeyButtonText;
late final Color messageBarHintText;
+ late final Color exportLogsButton;
}
final List availableColorSets = [
@@ -84,11 +87,12 @@ final ColorSet bubblyColorSet = ColorSet(
secondary: const Color.fromARGB(255, 255, 102, 179),
tertiary: const Color.fromARGB(255, 2, 45, 64),
text: const Color.fromARGB(255, 240, 246, 246),
- pWipeKeyButton: const Color.fromARGB(255, 165, 40, 255),
+ pWipeKeyButton: const Color.fromARGB(255, 255, 40, 183),
pInactiveTrack: const Color.fromARGB(255, 66, 191, 221),
pSendButton: const Color.fromARGB(255, 8, 75, 131),
pDropdownFocus: const Color.fromARGB(255, 165, 40, 255),
pMessageBarHintText: const Color.fromARGB(255, 66, 191, 221),
+ pExportLogsButton: const Color.fromARGB(255, 165, 40, 255),
);
/// If color set is not found then it returns default
From 4a9881f6c5a270f651fe7e9b80fe33a40c0b2c56 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 17:35:35 +0200
Subject: [PATCH 11/23] Rewrote logger creation and log messages + added log
for device and app information that is logged at logger creation.
---
lib/configuration.dart | 60 +++++++++++++++++++++++++++++++++---
lib/main.dart | 12 +++-----
lib/pages/settings_page.dart | 12 ++------
lib/utils/log.dart | 33 +++++++++++++++-----
lib/utils/storage.dart | 11 +++++--
pubspec.lock | 58 +++++++++++++++++++++++++++++++++-
pubspec.yaml | 2 ++
7 files changed, 156 insertions(+), 32 deletions(-)
diff --git a/lib/configuration.dart b/lib/configuration.dart
index a231629..42fac01 100644
--- a/lib/configuration.dart
+++ b/lib/configuration.dart
@@ -1,4 +1,11 @@
+import "package:device_info_plus/device_info_plus.dart" show AndroidDeviceInfo;
import "package:logging/logging.dart";
+import "package:package_info_plus/package_info_plus.dart" show PackageInfo;
+
+void externalConfiguration() {
+ // Required to be true if you want to change log level of loggers (e.g. allow config messages).
+ hierarchicalLoggingEnabled = true;
+}
class CryptographicConfiguration {
// Length in bytes
@@ -40,9 +47,6 @@ class MiscellaneousConfiguration {
}
class LoggingConfiguration {
- /// If encryption errors should be logged/printed
- static const bool verboseEncryptionError = false;
-
static const String loggerName = "VidarLogger";
static const bool extraVerboseLogs = true;
@@ -54,10 +58,56 @@ class LoggingConfiguration {
}
static String verboseLogMessage(final LogRecord log) {
- return "\n${log.sequenceNumber}: ${log.time.toIso8601String()}\nLevel: ${log.level.name}\nError: ${log.error}\nMessage: ${log.message}\nStack Trace: ${log.stackTrace}";
+ return """
+[${log.sequenceNumber}] ${log.time.toIso8601String()}
+\tLevel: ${log.level.name}
+\tError: ${log.error}
+\tMessage: ${log.message.replaceAll("\n", "\n\t")}
+\tStack Trace: ${log.stackTrace}
+ """;
}
static String conciseLogMessage(final LogRecord log) {
- return "\n${log.sequenceNumber}: ${log.time.toIso8601String()}\nLevel: ${log.level.name}\nMessage: ${log.message}";
+ return """
+[${log.sequenceNumber}] ${log.time.toIso8601String()}
+\tLevel: ${log.level.name}
+\tMessage: ${log.message.replaceAll("\n", "\n\t")}
+ """;
+ }
+
+ static String minimalLogMessage(final LogRecord log) {
+ return """
+[${log.sequenceNumber}] ${log.time.toIso8601String()}
+\t${log.message.replaceAll("\n", "\n\t")}
+ """;
+ }
+
+ static String initLog({
+ required final PackageInfo packageInfo,
+ required final AndroidDeviceInfo deviceInfo,
+ }) {
+ return """
+========== APP INFO ==========
+App Name: ${packageInfo.appName}
+Version: ${packageInfo.version}
+Build Number: ${packageInfo.buildNumber}
+======== DEVICE INFO =========
+Base OS: ${deviceInfo.version.baseOS == "" ? "unknown" : deviceInfo.version.baseOS}
+Bootloader: ${deviceInfo.bootloader}
+Total RAM: ${deviceInfo.physicalRamSize} MB
+Release ${deviceInfo.version.release}
+SDK: ${deviceInfo.version.sdkInt}
+Security Patch: ${deviceInfo.version.securityPatch}
+Manufacturer: ${deviceInfo.manufacturer}
+Brand: ${deviceInfo.brand}
+Model: ${deviceInfo.model}
+Emulator: ${!deviceInfo.isPhysicalDevice}
+Hardware Keystore: ${deviceInfo.systemFeatures.contains("android.hardware.hardware_keystore")}
+Telephony: ${deviceInfo.systemFeatures.contains("android.hardware.telephony")}
+Telephony Messaging: ${deviceInfo.systemFeatures.contains("android.hardware.telephony.messaging")}
+Telephony Subscription: ${deviceInfo.systemFeatures.contains("android.hardware.telephony.subscription")}
+Any Camera: ${deviceInfo.systemFeatures.contains("android.hardware.camera.any")}
+==============================
+ """;
}
}
diff --git a/lib/main.dart b/lib/main.dart
index c17cf59..3670e6c 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,10 +1,9 @@
import "package:flutter/material.dart";
import "package:permission_handler/permission_handler.dart";
+import "package:vidar/configuration.dart";
import "package:vidar/pages/contact_list.dart";
import "package:vidar/pages/no_sms_permission.dart";
import "package:vidar/utils/common_object.dart";
-import "package:vidar/utils/contact.dart";
-import "package:vidar/utils/settings.dart";
import "package:vidar/utils/sms.dart";
import "package:vidar/utils/storage.dart";
@@ -13,15 +12,12 @@ late PermissionStatus smsStatus;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
- final ContactList contactList = ContactList([]);
- final Settings settings = Settings();
- CommonObject.contactList = contactList;
- CommonObject.settings = settings;
+ externalConfiguration();
- await loadData(contactList, settings);
+ await loadData(CommonObject.contactList, CommonObject.settings);
SmsConstants(await retrieveSmsConstantsMap());
smsStatus = await Permission.sms.request();
-
+
runApp(const VidarApp());
}
diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart
index 706c10f..5b3d101 100644
--- a/lib/pages/settings_page.dart
+++ b/lib/pages/settings_page.dart
@@ -1,7 +1,5 @@
import "package:flutter/material.dart";
-import "package:logging/logging.dart";
import "package:permission_handler/permission_handler.dart";
-import "package:vidar/configuration.dart";
import "package:vidar/pages/contact_list.dart";
import "package:vidar/utils/colors.dart";
import "package:vidar/utils/common_object.dart";
@@ -53,7 +51,9 @@ class _SettingsPageState extends State {
final PermissionStatus manageExternalStorageStatus = await Permission
.manageExternalStorage
.request();
- if (manageExternalStorageStatus.isDenied) {
+ if (manageExternalStorageStatus.isGranted) {
+ createLogger();
+ } else {
if (mounted) {
showDialog(
context: context,
@@ -80,12 +80,6 @@ class _SettingsPageState extends State {
);
}
Settings.keepLogs = false;
- return;
- } else {
- CommonObject.logger = Logger(LoggingConfiguration.loggerName);
- CommonObject.logger!.onRecord.listen((final LogRecord log) {
- createLogger();
- });
}
} else {
if (CommonObject.logger != null) {
diff --git a/lib/utils/log.dart b/lib/utils/log.dart
index d5ce7f1..e344d99 100644
--- a/lib/utils/log.dart
+++ b/lib/utils/log.dart
@@ -1,7 +1,9 @@
import "dart:io";
+import "package:device_info_plus/device_info_plus.dart" show DeviceInfoPlugin;
import "package:flutter/material.dart";
import "package:logging/logging.dart";
+import "package:package_info_plus/package_info_plus.dart" show PackageInfo;
import "package:permission_handler/permission_handler.dart";
import "package:vidar/configuration.dart";
import "package:vidar/pages/contact_list.dart";
@@ -10,17 +12,32 @@ import "package:vidar/utils/navigation.dart";
import "package:vidar/utils/settings.dart";
import "package:vidar/widgets/error_popup.dart";
-void createLogger() {
+Future createLogger() async {
CommonObject.logger = Logger(LoggingConfiguration.loggerName);
+ if (hierarchicalLoggingEnabled) {
+ CommonObject.logger!.level = Level.ALL;
+ }
CommonObject.logger!.onRecord.listen((final LogRecord log) {
- if (log.level != Level.INFO && log.level != Level.CONFIG) {
- debugPrint(LoggingConfiguration.verboseLogMessage(log));
- CommonObject.logs.add(LoggingConfiguration.verboseLogMessage(log));
- } else {
- debugPrint(LoggingConfiguration.conciseLogMessage(log));
- CommonObject.logs.add(LoggingConfiguration.conciseLogMessage(log));
+ late final String logMessage;
+ switch (log.level) {
+ case Level.INFO:
+ logMessage = LoggingConfiguration.conciseLogMessage(log);
+ case Level.CONFIG:
+ logMessage = LoggingConfiguration.minimalLogMessage(log);
+ default:
+ logMessage = LoggingConfiguration.verboseLogMessage(log);
}
+
+ debugPrint(logMessage);
+ CommonObject.logs.add(logMessage);
});
+
+ CommonObject.logger!.config(
+ LoggingConfiguration.initLog(
+ packageInfo: await PackageInfo.fromPlatform(),
+ deviceInfo: await DeviceInfoPlugin().androidInfo,
+ ),
+ );
}
Future exportLogs({final BuildContext? context}) async {
@@ -84,3 +101,5 @@ Future exportLogs({final BuildContext? context}) async {
CommonObject.logger!.info('Logs have been exported to "${file.path}"');
}
}
+
+const Level initLog = const Level("INIT", 601);
diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart
index 7d74f30..525a5ba 100644
--- a/lib/utils/storage.dart
+++ b/lib/utils/storage.dart
@@ -80,7 +80,7 @@ Future loadData(
}
if (Settings.keepLogs) {
- createLogger();
+ await createLogger();
}
} on Exception catch (error, stackTrace) {
if (context != null && context.mounted) {
@@ -110,7 +110,14 @@ Future saveSettings(
sharedPreferences ?? await SharedPreferences.getInstance();
await prefs.setString("settings", jsonEncode(settings.toMap()));
if (Settings.keepLogs) {
- CommonObject.logger!.info("Settings: ${jsonEncode(settings.toMap())}");
+ // Showing Settings.keepLogs is redundant but it's there for consistency
+ CommonObject.logger!.config("""
+ ======== SETTINGS ========
+ Allow Unencrypted Messages: ${Settings.allowUnencryptedMessages}
+ Keep Logs: ${Settings.keepLogs}
+ Color set: ${Settings.colorSet.name}
+ Show Message Bar Hints: ${Settings.showMessageBarHints}
+ """);
}
} on Exception catch (error, stackTrace) {
if (context != null && context.mounted) {
diff --git a/pubspec.lock b/pubspec.lock
index 4dc3762..d1c4c43 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -57,6 +57,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.7.0"
+ device_info_plus:
+ dependency: "direct main"
+ description:
+ name: device_info_plus
+ sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "11.5.0"
+ device_info_plus_platform_interface:
+ dependency: transitive
+ description:
+ name: device_info_plus_platform_interface
+ sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.3"
fake_async:
dependency: transitive
description:
@@ -152,6 +168,22 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ http:
+ dependency: transitive
+ description:
+ name: http
+ sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.0"
+ http_parser:
+ dependency: transitive
+ description:
+ name: http_parser
+ sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.2"
js:
dependency: transitive
description:
@@ -216,6 +248,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.16.0"
+ package_info_plus:
+ dependency: "direct main"
+ description:
+ name: package_info_plus
+ sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191"
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.3.0"
+ package_info_plus_platform_interface:
+ dependency: transitive
+ description:
+ name: package_info_plus_platform_interface
+ sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.0"
path:
dependency: transitive
description:
@@ -501,6 +549,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.14.0"
+ win32_registry:
+ dependency: transitive
+ description:
+ name: win32_registry
+ sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.0"
xdg_directories:
dependency: transitive
description:
@@ -511,4 +567,4 @@ packages:
version: "1.1.0"
sdks:
dart: ">=3.8.1 <4.0.0"
- flutter: ">=3.27.0"
+ flutter: ">=3.29.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index fbd1a66..14d8596 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -18,6 +18,8 @@ dependencies:
logging: ^1.3.0
uuid: ^4.5.1
path_provider: ^2.1.5
+ device_info_plus: ^11.5.0
+ package_info_plus: ^8.3.0
dev_dependencies:
flutter_test:
From 51d0fbe2698d26d2765c7859acebb809f0587ca8 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 17:57:38 +0200
Subject: [PATCH 12/23] Removed unused packages
---
pubspec.lock | 87 +---------------------------------------------------
pubspec.yaml | 5 ---
2 files changed, 1 insertion(+), 91 deletions(-)
diff --git a/pubspec.lock b/pubspec.lock
index d1c4c43..bcb9b40 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -9,14 +9,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.13.0"
- boolean_selector:
- dependency: transitive
- description:
- name: boolean_selector
- sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
- url: "https://pub.dev"
- source: hosted
- version: "2.1.2"
characters:
dependency: transitive
description:
@@ -73,14 +65,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.3"
- fake_async:
- dependency: transitive
- description:
- name: fake_async
- sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
- url: "https://pub.dev"
- source: hosted
- version: "1.3.3"
ffi:
dependency: transitive
description:
@@ -158,11 +142,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.2"
- flutter_test:
- dependency: "direct dev"
- description: flutter
- source: sdk
- version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
@@ -192,30 +171,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.7"
- leak_tracker:
- dependency: transitive
- description:
- name: leak_tracker
- sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
- url: "https://pub.dev"
- source: hosted
- version: "10.0.9"
- leak_tracker_flutter_testing:
- dependency: transitive
- description:
- name: leak_tracker_flutter_testing
- sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
- url: "https://pub.dev"
- source: hosted
- version: "3.0.9"
- leak_tracker_testing:
- dependency: transitive
- description:
- name: leak_tracker_testing
- sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
- url: "https://pub.dev"
- source: hosted
- version: "3.0.1"
logging:
dependency: "direct main"
description:
@@ -224,14 +179,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.0"
- matcher:
- dependency: transitive
- description:
- name: matcher
- sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
- url: "https://pub.dev"
- source: hosted
- version: "0.12.17"
material_color_utilities:
dependency: transitive
description:
@@ -273,7 +220,7 @@ packages:
source: hosted
version: "1.9.1"
path_provider:
- dependency: "direct main"
+ dependency: transitive
description:
name: path_provider
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
@@ -461,22 +408,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
- stack_trace:
- dependency: transitive
- description:
- name: stack_trace
- sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
- url: "https://pub.dev"
- source: hosted
- version: "1.12.1"
- stream_channel:
- dependency: transitive
- description:
- name: stream_channel
- sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
- url: "https://pub.dev"
- source: hosted
- version: "2.1.4"
string_scanner:
dependency: transitive
description:
@@ -493,14 +424,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.2"
- test_api:
- dependency: transitive
- description:
- name: test_api
- sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
- url: "https://pub.dev"
- source: hosted
- version: "0.7.4"
typed_data:
dependency: transitive
description:
@@ -525,14 +448,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
- vm_service:
- dependency: transitive
- description:
- name: vm_service
- sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
- url: "https://pub.dev"
- source: hosted
- version: "15.0.0"
web:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 14d8596..538a565 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -17,13 +17,8 @@ dependencies:
flutter_secure_storage: ^9.2.4
logging: ^1.3.0
uuid: ^4.5.1
- path_provider: ^2.1.5
device_info_plus: ^11.5.0
package_info_plus: ^8.3.0
-dev_dependencies:
- flutter_test:
- sdk: flutter
-
flutter:
uses-material-design: true
From 9aca116fb4da0046f514e83219efbe55d646a6a8 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 18:00:11 +0200
Subject: [PATCH 13/23] typo
---
lib/widgets/conversation_widget.dart | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/widgets/conversation_widget.dart b/lib/widgets/conversation_widget.dart
index 0ee4909..899e78f 100644
--- a/lib/widgets/conversation_widget.dart
+++ b/lib/widgets/conversation_widget.dart
@@ -125,7 +125,7 @@ class _ConversationWidgetState extends State {
if (LoggingConfiguration.extraVerboseLogs &&
Settings.keepLogs) {
CommonObject.logger!.info(
- "Snapshot has not data for contact ${contact.uuid}",
+ "Snapshot has no data for contact ${contact.uuid}",
);
}
}
From f013694183178e95691b375165db0d9631248e8c Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 18:03:47 +0200
Subject: [PATCH 14/23] Added log when wiping keys
---
lib/pages/settings_page.dart | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart
index 5b3d101..d2f6f0b 100644
--- a/lib/pages/settings_page.dart
+++ b/lib/pages/settings_page.dart
@@ -4,6 +4,7 @@ import "package:vidar/pages/contact_list.dart";
import "package:vidar/utils/colors.dart";
import "package:vidar/utils/common_object.dart";
import "package:vidar/utils/log.dart";
+import "package:vidar/utils/navigation.dart";
import "package:vidar/utils/settings.dart";
import "package:vidar/utils/storage.dart";
import "package:vidar/widgets/boolean_setting.dart";
@@ -189,15 +190,12 @@ class _SettingsPageState extends State {
),
TextButton(
onPressed: () {
+ if (Settings.keepLogs) {
+ CommonObject.logger!.info("Wiping all keys...");
+ }
CommonObject.contactList.wipeKeys();
wipeSecureStorage();
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (final BuildContext context) =>
- const ContactListPage(),
- ),
- );
+ clearNavigatorAndPush(context, const ContactListPage());
},
child: const Text("Wipe Keys"),
),
From 6663e4875c569440df35afb8933c5ef4be1fea2b Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 18:07:54 +0200
Subject: [PATCH 15/23] removed linter rule "avoid_catches_without_on_clauses"
---
analysis_options.yaml | 1 -
1 file changed, 1 deletion(-)
diff --git a/analysis_options.yaml b/analysis_options.yaml
index b006f9f..d25f3cf 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -20,7 +20,6 @@ linter:
- annotate_overrides
- annotate_redeclares
- avoid_bool_literals_in_conditional_expressions
- - avoid_catches_without_on_clauses
- avoid_catching_errors
- avoid_empty_else
- avoid_escaping_inner_quotes
From ccd64bfcd92ff13739b4dbeab8b6c51426ee1f7d Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 18:22:01 +0200
Subject: [PATCH 16/23] Added new template for logs, made for common errors
that don't require stacktrace.
---
lib/configuration.dart | 9 +++++++++
lib/pages/edit_contact.dart | 2 +-
lib/utils/encryption.dart | 14 +++++++++++---
lib/utils/log.dart | 8 +++++---
lib/utils/sms.dart | 8 ++++----
5 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/lib/configuration.dart b/lib/configuration.dart
index 42fac01..2de75ba 100644
--- a/lib/configuration.dart
+++ b/lib/configuration.dart
@@ -67,6 +67,15 @@ class LoggingConfiguration {
""";
}
+ static String normalLogMessage(final LogRecord log) {
+ return """
+[${log.sequenceNumber}] ${log.time.toIso8601String()}
+\tLevel: ${log.level.name}
+\tError: ${log.error}
+\tMessage: ${log.message.replaceAll("\n", "\n\t")}
+ """;
+ }
+
static String conciseLogMessage(final LogRecord log) {
return """
[${log.sequenceNumber}] ${log.time.toIso8601String()}
diff --git a/lib/pages/edit_contact.dart b/lib/pages/edit_contact.dart
index 740acfd..73d70c8 100644
--- a/lib/pages/edit_contact.dart
+++ b/lib/pages/edit_contact.dart
@@ -161,7 +161,7 @@ class _EditContactPageState extends State {
clearNavigatorAndPush(context, const ContactListPage());
}
} else {
- CommonObject.logger!.warning(
+ CommonObject.logger!.info(
"Failed to add contact ${contact.uuid}",
);
}
diff --git a/lib/utils/encryption.dart b/lib/utils/encryption.dart
index 6bef012..0ece085 100644
--- a/lib/utils/encryption.dart
+++ b/lib/utils/encryption.dart
@@ -50,9 +50,9 @@ Future encryptMessage(final String message, final String key) async {
return CryptographicConfiguration.encryptionPrefix +
base64.encode(fullEncrypted);
- } on Exception catch (error, stackTrace) {
+ } catch (error, stackTrace) {
if (Settings.keepLogs) {
- CommonObject.logger!.warning(
+ CommonObject.logger!.finest(
"Failed to encrypt message",
error,
stackTrace,
@@ -119,11 +119,19 @@ Future decryptMessage(
);
final String decryptedMessage = utf8.decode(decryptedBytes);
return decryptedMessage;
- } on Exception catch (error, stackTrace) {
+ } on SecretBoxAuthenticationError catch (error) {
if (Settings.keepLogs) {
CommonObject.logger!.warning(
"Failed to decrypt message",
error,
+ );
+ }
+ return "${MiscellaneousConfiguration.errorPrefix}$ENCRYPTION_ERROR_DECRYPTION_FAILED";
+ } catch (error, stackTrace) {
+ if (Settings.keepLogs) {
+ CommonObject.logger!.finer(
+ "Failed to decrypt message",
+ error,
stackTrace,
);
}
diff --git a/lib/utils/log.dart b/lib/utils/log.dart
index e344d99..f5002b5 100644
--- a/lib/utils/log.dart
+++ b/lib/utils/log.dart
@@ -20,10 +20,12 @@ Future createLogger() async {
CommonObject.logger!.onRecord.listen((final LogRecord log) {
late final String logMessage;
switch (log.level) {
- case Level.INFO:
- logMessage = LoggingConfiguration.conciseLogMessage(log);
case Level.CONFIG:
logMessage = LoggingConfiguration.minimalLogMessage(log);
+ case Level.INFO:
+ logMessage = LoggingConfiguration.conciseLogMessage(log);
+ case Level.WARNING:
+ logMessage = LoggingConfiguration.normalLogMessage(log);
default:
logMessage = LoggingConfiguration.verboseLogMessage(log);
}
@@ -74,7 +76,7 @@ Future exportLogs({final BuildContext? context}) async {
}
if (Settings.keepLogs) {
- CommonObject.logger!.warning("Failed to export logs", error, stackTrace);
+ CommonObject.logger!.finest("Failed to export logs", error, stackTrace);
}
return;
diff --git a/lib/utils/sms.dart b/lib/utils/sms.dart
index 894286c..1cc5ed9 100644
--- a/lib/utils/sms.dart
+++ b/lib/utils/sms.dart
@@ -170,12 +170,12 @@ Future> querySms({final String? phoneNumber}) async {
}
}
return smsMessages;
- } on PlatformException catch (e) {
+ } on PlatformException catch (error, stackTrace) {
if (Settings.keepLogs) {
- CommonObject.logger!.warning(
+ CommonObject.logger!.finer(
"Sms query failed",
- e.message,
- e.stacktrace == null ? null : StackTrace.fromString(e.stacktrace!),
+ error,
+ stackTrace,
);
}
return [null];
From db61ecd6b13bf73708d90d86d9087ee7737cc959 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 20:20:47 +0200
Subject: [PATCH 17/23] Format
---
lib/main.dart | 2 +-
lib/pages/settings_page.dart | 9 +++++++--
lib/utils/encryption.dart | 5 +----
lib/utils/sms.dart | 6 +-----
4 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/lib/main.dart b/lib/main.dart
index 3670e6c..6ddf73c 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -17,7 +17,7 @@ void main() async {
await loadData(CommonObject.contactList, CommonObject.settings);
SmsConstants(await retrieveSmsConstantsMap());
smsStatus = await Permission.sms.request();
-
+
runApp(const VidarApp());
}
diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart
index d2f6f0b..dd99fcc 100644
--- a/lib/pages/settings_page.dart
+++ b/lib/pages/settings_page.dart
@@ -191,11 +191,16 @@ class _SettingsPageState extends State {
TextButton(
onPressed: () {
if (Settings.keepLogs) {
- CommonObject.logger!.info("Wiping all keys...");
+ CommonObject.logger!.info(
+ "Wiping all keys...",
+ );
}
CommonObject.contactList.wipeKeys();
wipeSecureStorage();
- clearNavigatorAndPush(context, const ContactListPage());
+ clearNavigatorAndPush(
+ context,
+ const ContactListPage(),
+ );
},
child: const Text("Wipe Keys"),
),
diff --git a/lib/utils/encryption.dart b/lib/utils/encryption.dart
index 0ece085..c9738c0 100644
--- a/lib/utils/encryption.dart
+++ b/lib/utils/encryption.dart
@@ -121,10 +121,7 @@ Future decryptMessage(
return decryptedMessage;
} on SecretBoxAuthenticationError catch (error) {
if (Settings.keepLogs) {
- CommonObject.logger!.warning(
- "Failed to decrypt message",
- error,
- );
+ CommonObject.logger!.warning("Failed to decrypt message", error);
}
return "${MiscellaneousConfiguration.errorPrefix}$ENCRYPTION_ERROR_DECRYPTION_FAILED";
} catch (error, stackTrace) {
diff --git a/lib/utils/sms.dart b/lib/utils/sms.dart
index 1cc5ed9..94d4f14 100644
--- a/lib/utils/sms.dart
+++ b/lib/utils/sms.dart
@@ -172,11 +172,7 @@ Future> querySms({final String? phoneNumber}) async {
return smsMessages;
} on PlatformException catch (error, stackTrace) {
if (Settings.keepLogs) {
- CommonObject.logger!.finer(
- "Sms query failed",
- error,
- stackTrace,
- );
+ CommonObject.logger!.finer("Sms query failed", error, stackTrace);
}
return [null];
}
From beadd532267ba8660ea0b7e61c91194838a467c1 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 20:50:03 +0200
Subject: [PATCH 18/23] Fixed time for speech bubbles, the bug was due to
creating Datetime from microseconds instead of miliseconds.
---
lib/utils/sms.dart | 4 ++--
lib/widgets/speech_bubble.dart | 11 ++++-------
2 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/lib/utils/sms.dart b/lib/utils/sms.dart
index 94d4f14..931680e 100644
--- a/lib/utils/sms.dart
+++ b/lib/utils/sms.dart
@@ -104,10 +104,10 @@ SmsMessage? _queryMapToSms(final Map smsMap) {
);
final int? type = int.tryParse(smsMap[SmsConstants.COLUMN_NAME_TYPE]!);
final String phoneNumber = smsMap[SmsConstants.COLUMN_NAME_ADDRESS]!;
- final DateTime date = DateTime.fromMicrosecondsSinceEpoch(
+ final DateTime date = DateTime.fromMillisecondsSinceEpoch(
int.parse(smsMap[SmsConstants.COLUMN_NAME_DATE]!),
);
- final DateTime dateSent = DateTime.fromMicrosecondsSinceEpoch(
+ final DateTime dateSent = DateTime.fromMillisecondsSinceEpoch(
int.parse(smsMap[SmsConstants.COLUMN_NAME_DATE_SENT]!),
);
final bool seen = int.parse(smsMap[SmsConstants.COLUMN_NAME_SEEN]!) != 0;
diff --git a/lib/widgets/speech_bubble.dart b/lib/widgets/speech_bubble.dart
index 4263ba9..123f911 100644
--- a/lib/widgets/speech_bubble.dart
+++ b/lib/widgets/speech_bubble.dart
@@ -50,17 +50,14 @@ class SpeechBubble extends StatelessWidget {
),
),
),
- // Temporarily disabled until fix
- /*Container(
- margin: EdgeInsets.only(top: 2, bottom: 2),
+ Container(
+ margin: const EdgeInsets.only(top: 2.0, bottom: 2.0),
child: Text(
(isMe ? "Sent at " : "Received at ") +
- (isMe
- ? message.dateSent!.toIso8601String().substring(11, 16)
- : message.date!.toIso8601String().substring(11, 16)),
+ message.date!.toIso8601String().substring(11, 16),
style: const TextStyle(color: Colors.white, fontSize: 8),
),
- ),*/
+ ),
],
),
),
From 1cd2a281deba7977c7dceef8990b148d243d6e13 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 20:54:49 +0200
Subject: [PATCH 19/23] Changed color of send button for default color set from
dark space cadet to a lavender tone + made hint text the same color.
---
lib/utils/colors.dart | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/utils/colors.dart b/lib/utils/colors.dart
index d53cf1a..c875b7f 100644
--- a/lib/utils/colors.dart
+++ b/lib/utils/colors.dart
@@ -56,7 +56,8 @@ final ColorSet vidarColorSet = ColorSet(
text: Colors.white,
pWipeKeyButton: const Color.fromARGB(255, 178, 34, 34),
pFloatingActionButton: const Color.fromARGB(255, 53, 22, 100),
- pMessageBarHintText: const Color.fromARGB(255, 103, 40, 198),
+ pMessageBarHintText: const Color.fromARGB(255, 172, 116, 255),
+ pSendButton: const Color.fromARGB(255, 172, 116, 255)
);
final ColorSet playaColorSet = ColorSet(
From 0aea5e9f067f290435c84f7c09a9084c10cb3aa5 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 21:00:15 +0200
Subject: [PATCH 20/23] Changed the color of the floating action button for the
default color set to a slightly more saturated tone
---
lib/utils/colors.dart | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/utils/colors.dart b/lib/utils/colors.dart
index c875b7f..27f7e0b 100644
--- a/lib/utils/colors.dart
+++ b/lib/utils/colors.dart
@@ -55,7 +55,7 @@ final ColorSet vidarColorSet = ColorSet(
tertiary: const Color.fromARGB(255, 177, 140, 25),
text: Colors.white,
pWipeKeyButton: const Color.fromARGB(255, 178, 34, 34),
- pFloatingActionButton: const Color.fromARGB(255, 53, 22, 100),
+ pFloatingActionButton: const Color.fromARGB(255, 39, 8, 86),
pMessageBarHintText: const Color.fromARGB(255, 172, 116, 255),
pSendButton: const Color.fromARGB(255, 172, 116, 255)
);
From 004cb38036a8227c8a5c064a7e39515c6a0b9cf9 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 21:30:17 +0200
Subject: [PATCH 21/23] The edit contact page now displays name and phone
number, (with option to also display key).
---
lib/pages/edit_contact.dart | 11 ++++++++++-
lib/pages/settings_page.dart | 16 ++++++++++++----
lib/utils/colors.dart | 2 +-
lib/utils/settings.dart | 8 +++++++-
4 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/lib/pages/edit_contact.dart b/lib/pages/edit_contact.dart
index 73d70c8..186f0ff 100644
--- a/lib/pages/edit_contact.dart
+++ b/lib/pages/edit_contact.dart
@@ -24,7 +24,7 @@ class _EditContactPageState extends State {
_EditContactPageState();
late Contact contact;
late ContactPageCaller caller;
- final TextEditingController encryptionKeyController = TextEditingController();
+ late final TextEditingController encryptionKeyController;
String? newName;
String? newKey;
@@ -35,6 +35,11 @@ class _EditContactPageState extends State {
super.initState();
contact = widget.contact;
caller = widget.caller;
+ encryptionKeyController = TextEditingController(
+ text: Settings.showEncryptionKeyInEditContact
+ ? contact.encryptionKey
+ : null,
+ );
}
@override
@@ -215,6 +220,7 @@ class _EditContactPageState extends State {
),
padding: const EdgeInsets.only(left: 10),
child: TextField(
+ controller: TextEditingController(text: contact.name),
decoration: InputDecoration(
hintText: "Name",
hintStyle: TextStyle(color: Settings.colorSet.text),
@@ -325,6 +331,9 @@ class _EditContactPageState extends State {
),
padding: const EdgeInsets.only(left: 10),
child: TextField(
+ controller: TextEditingController(
+ text: contact.phoneNumber,
+ ),
keyboardType: TextInputType.phone,
decoration: InputDecoration(
hintText: "Phone Number (international)",
diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart
index dd99fcc..b147855 100644
--- a/lib/pages/settings_page.dart
+++ b/lib/pages/settings_page.dart
@@ -21,22 +21,27 @@ class SettingsPage extends StatefulWidget {
class _SettingsPageState extends State {
_SettingsPageState();
- BooleanSetting allowUnencryptedMessages = BooleanSetting(
+ final BooleanSetting allowUnencryptedMessages = BooleanSetting(
setting: Settings.allowUnencryptedMessages,
settingText: "Send unencrypted messages when contact has no key",
);
- BooleanSetting keepLogs = BooleanSetting(
+ final BooleanSetting keepLogs = BooleanSetting(
setting: Settings.keepLogs,
settingText: "Keep Logs",
);
- BooleanSetting showMessageBarHints = BooleanSetting(
+ final BooleanSetting showEncryptionKeyInEditContact = BooleanSetting(
+ setting: Settings.showEncryptionKeyInEditContact,
+ settingText: "Show encryption key when editing contact",
+ );
+
+ final BooleanSetting showMessageBarHints = BooleanSetting(
setting: Settings.showMessageBarHints,
settingText: "Show message bar hints",
);
- ColorSetSelect colorSetSelect = ColorSetSelect(
+ final ColorSetSelect colorSetSelect = ColorSetSelect(
selectedSet: Settings.colorSet.name,
);
@@ -48,6 +53,8 @@ class _SettingsPageState extends State {
Future _save() async {
Settings.allowUnencryptedMessages = allowUnencryptedMessages.setting;
Settings.keepLogs = keepLogs.setting;
+ Settings.showEncryptionKeyInEditContact =
+ showEncryptionKeyInEditContact.setting;
if (Settings.keepLogs) {
final PermissionStatus manageExternalStorageStatus = await Permission
.manageExternalStorage
@@ -125,6 +132,7 @@ class _SettingsPageState extends State {
children: [
allowUnencryptedMessages,
keepLogs,
+ showEncryptionKeyInEditContact,
showMessageBarHints,
colorSetSelect,
],
diff --git a/lib/utils/colors.dart b/lib/utils/colors.dart
index 27f7e0b..aad3735 100644
--- a/lib/utils/colors.dart
+++ b/lib/utils/colors.dart
@@ -57,7 +57,7 @@ final ColorSet vidarColorSet = ColorSet(
pWipeKeyButton: const Color.fromARGB(255, 178, 34, 34),
pFloatingActionButton: const Color.fromARGB(255, 39, 8, 86),
pMessageBarHintText: const Color.fromARGB(255, 172, 116, 255),
- pSendButton: const Color.fromARGB(255, 172, 116, 255)
+ pSendButton: const Color.fromARGB(255, 172, 116, 255),
);
final ColorSet playaColorSet = ColorSet(
diff --git a/lib/utils/settings.dart b/lib/utils/settings.dart
index 86b14a4..d6d0030 100644
--- a/lib/utils/settings.dart
+++ b/lib/utils/settings.dart
@@ -8,15 +8,18 @@ class Settings {
static bool keepLogs = false;
- static ColorSet colorSet = vidarColorSet;
+ static bool showEncryptionKeyInEditContact = false;
static bool showMessageBarHints = true;
+ static ColorSet colorSet = vidarColorSet;
+
/// Get map of the state of all instance variable of Settings.
Map toMap() {
return {
"allowUnencryptedMessages": allowUnencryptedMessages,
"keepLogs": keepLogs,
+ "showEncryptionKeyInEditContact": showEncryptionKeyInEditContact,
"showMessageBarHints": showMessageBarHints,
"colorSet": colorSet.name,
};
@@ -26,6 +29,9 @@ class Settings {
/// If setting is not found then it goes to the default setting
void fromMap(final Map map) {
keepLogs = map["keepLogs"] as bool? ?? keepLogs;
+ showEncryptionKeyInEditContact =
+ map["showEncryptionKeyInEditContact"] as bool? ??
+ showEncryptionKeyInEditContact;
showMessageBarHints =
map["showMessageBarHints"] as bool? ?? showMessageBarHints;
colorSet = getColorSetFromName(map["colorSet"] as String? ?? "default");
From 4087354c3840b4233f2201550ac0c0f349b06e89 Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 22:06:11 +0200
Subject: [PATCH 22/23] Updated navigation for settings page to utilize
`clearNavigatorAndPush`
---
lib/pages/settings_page.dart | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart
index b147855..9ab808a 100644
--- a/lib/pages/settings_page.dart
+++ b/lib/pages/settings_page.dart
@@ -73,13 +73,7 @@ class _SettingsPageState extends State {
actions: [
TextButton(
onPressed: () {
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (final BuildContext context) =>
- const ContactListPage(),
- ),
- );
+ clearNavigatorAndPush(context, const ContactListPage());
},
child: const Text("Continue"),
),
@@ -101,22 +95,12 @@ class _SettingsPageState extends State {
if (mounted) {
saveSettings(CommonObject.settings, context: context);
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (final BuildContext context) => const ContactListPage(),
- ),
- );
+ clearNavigatorAndPush(context, const ContactListPage());
}
}
void _discard() {
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (final BuildContext context) => const ContactListPage(),
- ),
- );
+ clearNavigatorAndPush(context, const ContactListPage());
}
@override
From 7e6fea4745d7cd24205c7a638307c617f59dffde Mon Sep 17 00:00:00 2001
From: DrSolidDevil <51828495+DrSolidDevil@users.noreply.github.com>
Date: Sun, 13 Jul 2025 22:41:41 +0200
Subject: [PATCH 23/23] Updated changelog to include 1.1.0-beta
---
CHANGELOG.md | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6807534..f9f5f60 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,31 @@
+## [1.1.0-beta](https://github.com/DrSolidDevil/Vidar/compare/v1.0.3-beta...v1.1.0-beta) (2025-07-13)
+
+> This version of Vidar introduces color sets! You can now choose how your experience will look. In addition to color sets, now you can export logs at any time through the settings. This version also finally introduces the ability to see the time a message was sent/received.
+
+### New Features
+* Color sets for Vidar currently there are four color sets (including default). [`642c3cb`](https://github.com/DrSolidDevil/Vidar/commit/642c3cb95b271b4a59e451042c7fba6dbc9c8198) [`7c8b6a2`](https://github.com/DrSolidDevil/Vidar/commit/7c8b6a27091b0fcbcef068cbdcfd49f73d7b81bc) [`1cd2a28`](https://github.com/DrSolidDevil/Vidar/commit/1cd2a281deba7977c7dceef8990b148d243d6e13) [`0aea5e9`](https://github.com/DrSolidDevil/Vidar/commit/0aea5e9f067f290435c84f7c09a9084c10cb3aa5)
+* Ability to export logs at any time using a button on the settings page. [`9ae93a9`](https://github.com/DrSolidDevil/Vidar/commit/9ae93a9304b2644da57b72c15ee4e7101f639341)
+* Messages now display the time it was sent/received. [`beadd53`](https://github.com/DrSolidDevil/Vidar/commit/beadd532267ba8660ea0b7e61c91194838a467c1)
+* Edit contact page now shows current name, phone number and optionally the encryption key (by default not shown) [`004cb38`](https://github.com/DrSolidDevil/Vidar/commit/004cb38036a8227c8a5c064a7e39515c6a0b9cf9)
+
+### Bug Fixes
+* Fixed faulty save logic for edit_contact.dart. [`1a336aa`](https://github.com/DrSolidDevil/Vidar/commit/1a336aaea631f39e64b88e62519036bc3ac796a9)
+* Fixed SMS dates when retrieving from map sent via method channel. [`beadd53`](https://github.com/DrSolidDevil/Vidar/commit/beadd532267ba8660ea0b7e61c91194838a467c1)
+
+### Other Changes
+* Added pull-request templates. [`c2a31a3`](https://github.com/DrSolidDevil/Vidar/commit/c2a31a3516d4918a4a047b59079074dbfad05646)
+* Created changelog. [`3e8177c`](https://github.com/DrSolidDevil/Vidar/commit/3e8177cd76368379a5eb42b556e45deeac08435d)
+* Changed keyboard type of the phone number field on the edit contact page to a phone number optimized one. [`6b71f84`](https://github.com/DrSolidDevil/Vidar/commit/6b71f84ada9b4e4b174ae4c49878e8f5231752aa)
+* Navigation standardization. [`ce58482`](https://github.com/DrSolidDevil/Vidar/commit/ce58482f1f167ccb4718b28444523155de199212) [`4087354`](https://github.com/DrSolidDevil/Vidar/commit/4087354c3840b4233f2201550ac0c0f349b06e89)
+* Dialog to export logs no longer utilizes ErrorPopup [`8eb897a`](https://github.com/DrSolidDevil/Vidar/commit/8eb897a9eca87de5edaf9e0834f45f8348003409)
+* Rewrote logging in an effort to improve DX. [`4a9881f`](https://github.com/DrSolidDevil/Vidar/commit/4a9881f6c5a270f651fe7e9b80fe33a40c0b2c56) [`f013694`](https://github.com/DrSolidDevil/Vidar/commit/f013694183178e95691b375165db0d9631248e8c) [`ccd64bf`](https://github.com/DrSolidDevil/Vidar/commit/ccd64bfcd92ff13739b4dbeab8b6c51426ee1f7d)
+* Removed unused packages. [`51d0fbe`](https://github.com/DrSolidDevil/Vidar/commit/51d0fbe2698d26d2765c7859acebb809f0587ca8)
+* Removed linter rule "avoid_catches_without_on_clauses" [`6663e48`](https://github.com/DrSolidDevil/Vidar/commit/6663e4875c569440df35afb8933c5ef4be1fea2b)
+* Minor visual enhancements [`f7c8f78`](https://github.com/DrSolidDevil/Vidar/commit/f7c8f78eac044fb0e6e51a80660fa16c99bf8582)
+* Typo fixed. [`9aca116`](https://github.com/DrSolidDevil/Vidar/commit/9aca116fb4da0046f514e83219efbe55d646a6a8)
+
+
+
## [1.0.3-beta](https://github.com/DrSolidDevil/Vidar/compare/v1.0.2-beta...v1.0.3-beta) (2025-07-10)
> No real changes for the end user; upgrading is not necessary.