Merge pull request #262 from yaso-meth/V.1.2.3

V.1.2.3
This commit is contained in:
yaso-meth
2025-11-10 17:03:44 +02:00
committed by GitHub
98 changed files with 2811 additions and 228 deletions

View File

@@ -11,10 +11,17 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:replace="android:maxSdkVersion"
android:maxSdkVersion="29"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32"
tools:replace="android:maxSdkVersion" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<application
android:label="MIH"
@@ -46,6 +53,10 @@
android:name="flutter-deeplink"
android:value="true"
/>
<!-- Shortcut Icons -->
<meta-data
android:name="mih_shortcut_icons"
android:resource="@array/mih_shortcut_icons" />
<!-- New Deep Linking -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
@@ -99,5 +110,8 @@
<intent>
<action android:name="android.intent.action.TTS_SERVICE" />
</intent>
<intent>
<action android:name="android.speech.RecognitionService" />
</intent>
</queries>
</manifest>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 27 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="@color/mih_icon_background" />
<!-- <size android:width="48dp" android:height="48dp"/> -->
</shape>
</item>
<item
android:drawable="@drawable/calculator"
android:width="48dp"
android:height="48dp"
android:gravity="center" />
</layer-list>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="@color/mih_icon_background" />
<!-- <size android:width="48dp" android:height="48dp"/> -->
</shape>
</item>
<item
android:drawable="@drawable/mih_logo"
android:width="48dp"
android:height="48dp"
android:gravity="center" />
</layer-list>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="@color/mih_icon_background" />
<!-- <size android:width="48dp" android:height="48dp"/> -->
</shape>
</item>
<item
android:drawable="@drawable/mzansi_ai"
android:width="48dp"
android:height="48dp"
android:gravity="center" />
</layer-list>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="@color/mih_icon_background" />
<!-- <size android:width="48dp" android:height="48dp"/> -->
</shape>
</item>
<item
android:drawable="@drawable/mzansi_wallet"
android:width="48dp"
android:height="48dp"
android:gravity="center" />
</layer-list>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="mih_shortcut_icons">
<item>@drawable/mih_home_sc</item>
<item>@drawable/mzansi_wallet_sc</item>
<item>@drawable/mzansi_ai_sc</item>
<item>@drawable/mih_calculator_sc</item>
</array>
</resources>

View File

@@ -1,4 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#3A4454</color>
<color name="ic_launcher_background">#6641b2</color>
<!-- Women For Change -->
<color name="mih_icon_background">#6641b2</color>
<color name="mih_icon_foreground">#E0D1FF</color>
<!-- Original -->
<!-- <color name="mih_icon_background">#3A4454</color>
<color name="mih_icon_foreground">#bedcfe</color> -->
</resources>

File diff suppressed because one or more lines are too long

View File

@@ -1,32 +1,46 @@
# flutter pub run flutter_launcher_icons
flutter_launcher_icons:
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_app_icon.png"
# Original
# image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_logo_app.png"
# Women For Change
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_logo_app_w4c.png"
android: "launcher_icon"
# image_path_android: "assets/icon/icon.png"
min_sdk_android: 21 # android min sdk min:16, default 21
adaptive_icon_background: "#3A4454"
adaptive_icon_foreground: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_app_icon.png"
# adaptive_icon_monochrome: "assets/icon/monochrome.png"
# Original
# adaptive_icon_background: "#3A4454"
# adaptive_icon_foreground: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_logo_app.png"
# Women For Change
adaptive_icon_background: "#6641b2"
adaptive_icon_foreground: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_logo_app_w4c.png"
ios: true
image_path_ios: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_app_icon.png"
# Original
# image_path_ios: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_logo_app.png"
# Women For Change
image_path_ios: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_logo_app_w4c.png"
remove_alpha_channel_ios: true
# image_path_ios_dark_transparent: "assets/icon/icon_dark.png"
# image_path_ios_tinted_grayscale: "assets/icon/icon_tinted.png"
# desaturate_tinted_to_grayscale_ios: true
web:
generate: true
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/circle_logo.png"
background_color: "#3A4454"
theme_color: "#3A4454"
# Original
# image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_logo_web.png"
# background_color: "#3A4454"
# theme_color: "#3A4454"
# Women For Change
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_logo_web_w4c.png"
background_color: "#6641b2"
theme_color: "#6641b2"
windows:
generate: true
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/circle_logo.png"
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_logo_web.png"
icon_size: 48 # min:48, max:256, default: 48
macos:
generate: true
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/circle_logo.png"
image_path: "lib/mih_components/mih_package_components/assets/images/app_icon/mih_logo_web.png"

View File

@@ -1,6 +1,15 @@
PODS:
- app_settings (5.1.1):
- Flutter
- AppCheckCore (11.2.0):
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- PromisesObjC (~> 2.4)
- camera_avfoundation (0.0.1):
- Flutter
- CwlCatchException (2.2.1):
- CwlCatchExceptionSupport (~> 2.2.1)
- CwlCatchExceptionSupport (2.2.1)
- device_info_plus (0.0.1):
- Flutter
- DKImagePickerController/Core (4.3.9):
@@ -40,6 +49,50 @@ PODS:
- Flutter
- file_saver (0.0.1):
- Flutter
- file_selector_ios (0.0.1):
- Flutter
- Firebase/Auth (12.4.0):
- Firebase/CoreOnly
- FirebaseAuth (~> 12.4.0)
- Firebase/CoreOnly (12.4.0):
- FirebaseCore (~> 12.4.0)
- firebase_app_check (0.4.1-2):
- Firebase/CoreOnly (~> 12.4.0)
- firebase_core
- FirebaseAppCheck (~> 12.4.0)
- Flutter
- firebase_auth (6.1.2):
- Firebase/Auth (= 12.4.0)
- firebase_core
- Flutter
- firebase_core (4.2.1):
- Firebase/CoreOnly (= 12.4.0)
- Flutter
- FirebaseAppCheck (12.4.0):
- AppCheckCore (~> 11.0)
- FirebaseAppCheckInterop (~> 12.4.0)
- FirebaseCore (~> 12.4.0)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/UserDefaults (~> 8.1)
- FirebaseAppCheckInterop (12.4.0)
- FirebaseAuth (12.4.0):
- FirebaseAppCheckInterop (~> 12.4.0)
- FirebaseAuthInterop (~> 12.4.0)
- FirebaseCore (~> 12.4.0)
- FirebaseCoreExtension (~> 12.4.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/Environment (~> 8.1)
- GTMSessionFetcher/Core (< 6.0, >= 3.4)
- RecaptchaInterop (~> 101.0)
- FirebaseAuthInterop (12.4.0)
- FirebaseCore (12.4.0):
- FirebaseCoreInternal (~> 12.4.0)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Logger (~> 8.1)
- FirebaseCoreExtension (12.4.0):
- FirebaseCore (~> 12.4.0)
- FirebaseCoreInternal (12.4.0):
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- fl_downloader (0.0.1):
- Flutter
- Flutter (1.0.0)
@@ -63,6 +116,33 @@ PODS:
- FBAudienceNetwork (= 6.20.1)
- Google-Mobile-Ads-SDK (~> 12.0)
- GoogleUserMessagingPlatform (3.0.0)
- GoogleUtilities/AppDelegateSwizzler (8.1.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Privacy
- GoogleUtilities/Environment (8.1.0):
- GoogleUtilities/Privacy
- GoogleUtilities/Logger (8.1.0):
- GoogleUtilities/Environment
- GoogleUtilities/Privacy
- GoogleUtilities/Network (8.1.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Privacy
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (8.1.0)":
- GoogleUtilities/Privacy
- GoogleUtilities/Privacy (8.1.0)
- GoogleUtilities/Reachability (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilities/UserDefaults (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GTMSessionFetcher/Core (5.0.0)
- image_picker_ios (0.0.1):
- Flutter
- local_auth_darwin (0.0.1):
- Flutter
- FlutterMacOS
@@ -76,6 +156,12 @@ PODS:
- FlutterMacOS
- printing (1.0.0):
- Flutter
- PromisesObjC (2.4.0)
- quick_actions_ios (0.0.1):
- Flutter
- RecaptchaInterop (101.0.0)
- record_ios (1.1.0):
- Flutter
- screen_brightness_ios (0.1.0):
- Flutter
- SDWebImage (5.20.0):
@@ -86,6 +172,10 @@ PODS:
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- speech_to_text (7.2.0):
- CwlCatchException
- Flutter
- FlutterMacOS
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
@@ -100,9 +190,14 @@ PODS:
DEPENDENCIES:
- app_settings (from `.symlinks/plugins/app_settings/ios`)
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- file_saver (from `.symlinks/plugins/file_saver/ios`)
- file_selector_ios (from `.symlinks/plugins/file_selector_ios/ios`)
- firebase_app_check (from `.symlinks/plugins/firebase_app_check/ios`)
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- fl_downloader (from `.symlinks/plugins/fl_downloader/ios`)
- Flutter (from `Flutter`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
@@ -110,14 +205,18 @@ DEPENDENCIES:
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
- gma_mediation_meta (from `.symlinks/plugins/gma_mediation_meta/ios`)
- google_mobile_ads (from `.symlinks/plugins/google_mobile_ads/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- printing (from `.symlinks/plugins/printing/ios`)
- quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`)
- record_ios (from `.symlinks/plugins/record_ios/ios`)
- screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- speech_to_text (from `.symlinks/plugins/speech_to_text/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- syncfusion_flutter_pdfviewer (from `.symlinks/plugins/syncfusion_flutter_pdfviewer/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
@@ -125,24 +224,49 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- AppCheckCore
- CwlCatchException
- CwlCatchExceptionSupport
- DKImagePickerController
- DKPhotoGallery
- FBAudienceNetwork
- Firebase
- FirebaseAppCheck
- FirebaseAppCheckInterop
- FirebaseAuth
- FirebaseAuthInterop
- FirebaseCore
- FirebaseCoreExtension
- FirebaseCoreInternal
- Google-Mobile-Ads-SDK
- GoogleMobileAdsMediationFacebook
- GoogleUserMessagingPlatform
- GoogleUtilities
- GTMSessionFetcher
- PromisesObjC
- RecaptchaInterop
- SDWebImage
- SwiftyGif
EXTERNAL SOURCES:
app_settings:
:path: ".symlinks/plugins/app_settings/ios"
camera_avfoundation:
:path: ".symlinks/plugins/camera_avfoundation/ios"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
file_saver:
:path: ".symlinks/plugins/file_saver/ios"
file_selector_ios:
:path: ".symlinks/plugins/file_selector_ios/ios"
firebase_app_check:
:path: ".symlinks/plugins/firebase_app_check/ios"
firebase_auth:
:path: ".symlinks/plugins/firebase_auth/ios"
firebase_core:
:path: ".symlinks/plugins/firebase_core/ios"
fl_downloader:
:path: ".symlinks/plugins/fl_downloader/ios"
Flutter:
@@ -157,6 +281,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/gma_mediation_meta/ios"
google_mobile_ads:
:path: ".symlinks/plugins/google_mobile_ads/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
local_auth_darwin:
:path: ".symlinks/plugins/local_auth_darwin/darwin"
mobile_scanner:
@@ -167,12 +293,18 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
printing:
:path: ".symlinks/plugins/printing/ios"
quick_actions_ios:
:path: ".symlinks/plugins/quick_actions_ios/ios"
record_ios:
:path: ".symlinks/plugins/record_ios/ios"
screen_brightness_ios:
:path: ".symlinks/plugins/screen_brightness_ios/ios"
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
speech_to_text:
:path: ".symlinks/plugins/speech_to_text/darwin"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
syncfusion_flutter_pdfviewer:
@@ -184,12 +316,28 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
app_settings: 5127ae0678de1dcc19f2293271c51d37c89428b2
AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f
camera_avfoundation: be3be85408cd4126f250386828e9b1dfa40ab436
CwlCatchException: 7acc161b299a6de7f0a46a6ed741eae2c8b4d75a
CwlCatchExceptionSupport: 54ccab8d8c78907b57f99717fb19d4cc3bce02dc
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
FBAudienceNetwork: 08e86d63a05b3a5a59414af12e4af8d756943c80
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
file_selector_ios: f92e583d43608aebc2e4a18daac30b8902845502
Firebase: f07b15ae5a6ec0f93713e30b923d9970d144af3e
firebase_app_check: 61fb3578a0761c806533482aca240a2d5cc5b5ef
firebase_auth: 9225db04db5d8e3b46dc8940e04bc6aec6833e27
firebase_core: f1aafb21c14f497e5498f7ffc4dc63cbb52b2594
FirebaseAppCheck: 73721d98fa29cf199da6004e57715cbaddd49651
FirebaseAppCheckInterop: f734c802f21fe1da0837708f0f9a27218c8a4ed0
FirebaseAuth: 4a2aed737c84114a9d9b33d11ae1b147d6b94889
FirebaseAuthInterop: 858e6b754966e70740a4370dd1503dfffe6dbb49
FirebaseCore: bb595f3114953664e3c1dc032f008a244147cfd3
FirebaseCoreExtension: 7e1f7118ee970e001a8013719fb90950ee5e0018
FirebaseCoreInternal: d7f5a043c2cd01a08103ab586587c1468047bca6
fl_downloader: dc99aa8dd303f862cccb830087f37acc9b0156ee
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
@@ -200,15 +348,23 @@ SPEC CHECKSUMS:
google_mobile_ads: 535223588a6791b7a3cc3513a1bc7b89d12f3e62
GoogleMobileAdsMediationFacebook: b11a92ae3bfdae19853b882252b7e62791c18162
GoogleUserMessagingPlatform: f8d0cdad3ca835406755d0a69aa634f00e76d576
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
GTMSessionFetcher: 02d6e866e90bc236f48a703a041dfe43e6221a29
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
printing: 54ff03f28fe9ba3aa93358afb80a8595a071dd07
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
quick_actions_ios: 4b07fb49d8d8f3518d7565fbb7a91014067a7d82
RecaptchaInterop: 11e0b637842dfb48308d242afc3f448062325aba
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
screen_brightness_ios: 9953fd7da5bd480f1a93990daeec2eb42d4f3b52
SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
speech_to_text: 3b313d98516d3d0406cea424782ec25470c59d19
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
syncfusion_flutter_pdfviewer: 90dc48305d2e33d4aa20681d1e98ddeda891bc14

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,16 @@
{
"images" : [
{
"filename" : "calculator.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,16 @@
{
"images" : [
{
"filename" : "mih_logo.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,16 @@
{
"images" : [
{
"filename" : "mzansi_ai.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,16 @@
{
"images" : [
{
"filename" : "mzansi_wallet.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -2,6 +2,16 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to your microphone to enable voice input for the chat.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app uses speech recognition to convert your voice messages into text.</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to your microphone to enable voice input for the chat.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app uses speech recognition to convert your voice messages into text.</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>SKAdNetworkItems</key>

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/about_mih_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_authentication_provider.dart';
@@ -12,8 +13,8 @@ import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_direct
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:provider/provider.dart';
import 'package:quick_actions/quick_actions.dart';
import 'package:upgrader/upgrader.dart';
import 'mih_config/mih_env.dart';
import 'mih_config/mih_theme.dart';
@@ -35,41 +36,62 @@ class MzansiInnovationHub extends StatefulWidget {
class _MzansiInnovationHubState extends State<MzansiInnovationHub> {
late MihTheme theme;
final QuickActions quickActions = QuickActions();
String shortcut = 'no action set';
Color getPrimany() {
return MihColors.getPrimaryColor(theme.mode == "Dark");
}
String getTitle() {
if (AppEnviroment.getEnv() == "Dev") {
return "Dev | MIH App: Mzansi Innovation Hub";
} else {
return "MIH App: Mzansi Innovation Hub";
}
}
void changeTheme(ThemeMode themeMode) {
setState(() {
if (themeMode == ThemeMode.light) {
setState(() {
theme.mode = "Light";
});
} else if (themeMode == ThemeMode.dark) {
setState(() {
theme.mode = "Dark";
});
} else {
setState(() {
theme.mode = "Dark";
});
void _initializeQuickActions() {
quickActions.initialize((String shortcutType) {
setState(() {
shortcut = shortcutType;
});
if (shortcutType == 'mihHome') {
KenLogger.success("ShortCut: mihHome");
widget.router.goNamed("mihHome");
}
if (shortcutType == 'mzansiWallet') {
KenLogger.success("ShortCut: mzansiWallet");
widget.router.goNamed("mzansiWallet");
}
if (shortcutType == 'mzansiAi') {
KenLogger.success("ShortCut: mzansiAi");
widget.router.goNamed("mzansiAi");
}
if (shortcutType == 'mihCalculator') {
KenLogger.success("ShortCut: mihCalculator");
widget.router.goNamed("mihCalculator");
}
});
// Set the quick actions
quickActions.setShortcutItems(<ShortcutItem>[
const ShortcutItem(
type: 'mzansiWallet',
localizedTitle: 'Mzansi Wallet',
icon: 'mzansi_wallet_sc',
),
const ShortcutItem(
type: 'mzansiAi',
localizedTitle: 'Mzansi AI',
icon: 'mzansi_ai_sc',
),
const ShortcutItem(
type: 'mihCalculator',
localizedTitle: 'MIH Calc',
icon: 'mih_calculator_sc',
),
]).then((void _) {
setState(() {
if (shortcut == 'no action set') {
shortcut = 'mih_home_sc';
}
});
});
}
@override
void initState() {
theme = MihTheme();
super.initState();
_initializeQuickActions();
theme = MihTheme();
theme.mode = "Dark";
theme.platform = Theme.of(context).platform;
}
@@ -78,7 +100,6 @@ class _MzansiInnovationHubState extends State<MzansiInnovationHub> {
Widget build(BuildContext context) {
double width = MediaQuery.sizeOf(context).width;
theme.setScreenType(width);
precacheImage(theme.loadingImage(), context);
return MultiProvider(
providers: [
ChangeNotifierProvider(
@@ -119,7 +140,9 @@ class _MzansiInnovationHubState extends State<MzansiInnovationHub> {
),
],
child: MaterialApp.router(
title: getTitle(),
title: AppEnviroment.getEnv() == "Dev"
? "Dev | MIH App: Mzansi Innovation Hub"
: "MIH App: Mzansi Innovation Hub",
themeMode: ThemeMode.dark,
theme: theme.getThemeData(),
darkTheme: theme.getThemeData(),

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import '../../main.dart';
import 'package:gif_view/gif_view.dart';
class Mihloadingcircle extends StatefulWidget {
final String? message;
@@ -11,8 +11,11 @@ class Mihloadingcircle extends StatefulWidget {
State<Mihloadingcircle> createState() => _MihloadingcircleState();
}
class _MihloadingcircleState extends State<Mihloadingcircle> {
// final GifController _controller = GifController();
class _MihloadingcircleState extends State<Mihloadingcircle>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
late double popUpPaddingSize;
late double popUpWidth;
late double? popUpheight;
@@ -38,14 +41,26 @@ class _MihloadingcircleState extends State<Mihloadingcircle> {
@override
void initState() {
//_controller.animateTo(26);
super.initState();
checkScreenSize();
_controller = AnimationController(
duration: const Duration(
milliseconds: 500), // Duration for one pulse (grow and shrink)
vsync: this,
);
_animation = Tween<double>(
begin: 200,
end: 200 * 0.5, // Pulse to 50% of the initial size
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut, // Smooth start and end of the pulse
));
_controller.repeat(reverse: true);
}
@override
void dispose() {
// _controller.dispose();
_controller.dispose();
super.dispose();
}
@@ -70,13 +85,22 @@ class _MihloadingcircleState extends State<Mihloadingcircle> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
GifView.asset(
MzansiInnovationHub.of(context)!
.theme
.loadingImageLocation(),
height: 200,
SizedBox(
width: 200,
frameRate: 30,
height: 200,
child: AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Icon(
MihIcons.mihLogo,
size: _animation
.value, // The size changes based on the animation value
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
);
},
),
),
widget.message != null
? Text(

View File

@@ -1,12 +1,55 @@
import 'package:flutter/material.dart';
import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart';
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/ollama_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
class MzansiAiProvider extends ChangeNotifier {
bool ttsOn;
int toolIndex;
String? startUpQuestion;
late OllamaProvider ollamaProvider;
MzansiAiProvider({
this.toolIndex = 0,
});
this.ttsOn = false,
}) {
ollamaProvider = OllamaProvider(
baseUrl: "${AppEnviroment.baseAiUrl}/api",
model: AppEnviroment.getEnv() == "Prod" ? 'gemma3n:e4b' : "gemma3:1b",
systemPrompt: "You are Mzansi AI, a helpful and friendly AI assistant running on the 'MIH App'.\n" +
"The MIH App was created by 'Mzansi Innovation Hub', a South African-based startup company." +
"Your primary purpose is to assist users by answering general questions and helping with creative writing tasks or any other task a user might have for you.\n" +
"Maintain a casual and friendly tone, but always remain professional.\n" +
"Strive for a balance between being empathetic and delivering factual information accurately.\n" +
"You may use lighthearted or playful language if the context is appropriate and enhances the user experience.\n" +
"You operate within the knowledge domain of the 'MIH App'.\n" +
"Here is a description of the MIH App and its features:\n" +
"MIH App Description: MIH is the first super app of Mzansi, designed to streamline both personal and business life. It's an all-in-one platform for managing professional profiles, teams, appointments, and quick calculations. \n" +
"Key Features:\n" +
"- Mzansi Profile: Central hub for managing personal and business information, including business team details." +
"- Mzansi Wallet: Digitally store loyalty cards.\n" +
"- Patient Manager (For Medical Practices): Seamless patient appointment scheduling and data management.\n" +
"- Mzansi AI: Your friendly AI assistant for quick answers and support (that's you!).\n" +
"- Mzansi Directory: A place to search and find out more about the people and businesses across Mzansi.\n" +
"- Calendar: Integrated calendar for managing personal and business appointments.\n" +
"- Calculator: Simple calculator with tip and forex calculation functionality.\n" +
"- MIH Minesweeper: The first game from MIH! It's the classic brain-teaser ready to entertain you no matter where you are.\n" +
"- MIH Access: Manage and view profile access security.\n" +
"**Core Rules and Guidelines:**\n" +
"- **Accuracy First:** Always prioritize providing correct information.\n" +
"- **Uncertainty Handling:** If you are unsure about an answer, politely respond with: 'Please bear with us as we are still learning and do not have all the answers.'\n" +
"- **Response Length:** Aim to keep responses under 250 words. If a more comprehensive answer is required, exceed this limit but offer to elaborate further (e.g., 'Would you like me to elaborate on this topic?').\n" +
"- **Language & Safety:** Never use offensive language or generate harmful content. If a user presses for information that is inappropriate or out of bounds, clearly state why you cannot provide it (e.g., 'I cannot assist with that request as it goes against my safety guidelines.').\n" +
"- **Out-of-Scope Questions:** - If a question is unclear, ask the user to rephrase or clarify it. - If a question is entirely out of your scope and you cannot provide a useful answer, admit you don't know. - If a user is unhappy with your response or needs further assistance beyond your capabilities, suggest they visit the 'Mzansi Innovation Hub Social Media Pages' for more direct support. Do not provide specific links, just refer to the pages generally.\n" +
"- **Target Audience:** Adapt your explanations to beginners and intermediate users, but be prepared for more complex questions from expert users. Ensure your language is clear and easy to understand.\n",
)..addListener(() {
notifyListeners(); // Forward OllamaProvider notifications
});
}
void reset() {
toolIndex = 0;
@@ -19,8 +62,267 @@ class MzansiAiProvider extends ChangeNotifier {
notifyListeners();
}
void setTTSstate(bool ttsOn) {
this.ttsOn = ttsOn;
notifyListeners();
}
void setStartUpQuestion(String? question) {
startUpQuestion = question;
notifyListeners();
}
void clearStartUpQuestion() {
startUpQuestion = null;
}
MarkdownStyleSheet getLlmChatMarkdownStyle(BuildContext context) {
TextStyle body = TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 16,
fontWeight: FontWeight.w400,
);
TextStyle heading1 = TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 24,
fontWeight: FontWeight.w400,
);
TextStyle heading2 = TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.w400,
);
TextStyle code = TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 16,
fontWeight: FontWeight.w400,
);
BoxDecoration codeBlock = BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
color: MihColors.getHighlightColor(
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(76),
blurRadius: 8,
offset: Offset(2, 2),
),
],
);
return MarkdownStyleSheet(
a: body,
blockquote: body,
checkbox: body,
del: body,
em: body.copyWith(fontStyle: FontStyle.italic),
h1: heading1,
h2: heading2,
h3: body.copyWith(fontWeight: FontWeight.bold),
h4: body,
h5: body,
h6: body,
listBullet: body,
img: body,
strong: body.copyWith(fontWeight: FontWeight.bold),
p: body,
tableBody: body,
tableHead: body,
code: code,
codeblockDecoration: codeBlock,
);
}
LlmChatViewStyle? getChatStyle(BuildContext context) {
return LlmChatViewStyle(
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
progressIndicatorColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
menuColor: Colors.black,
// MihColors.getGreenColor(
// MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
disabledButtonStyle: ActionButtonStyle(
icon: MihIcons.mzansiAi,
iconColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconDecoration: BoxDecoration(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
),
recordButtonStyle: ActionButtonStyle(
iconColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconDecoration: BoxDecoration(
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
submitButtonStyle: ActionButtonStyle(
icon: Icons.send,
iconColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconDecoration: BoxDecoration(
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
stopButtonStyle: ActionButtonStyle(
iconColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconDecoration: BoxDecoration(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
actionButtonBarDecoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
// Mzansi AI Chat Style
llmMessageStyle: LlmMessageStyle(
icon: MihIcons.mzansiAi,
iconColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
iconDecoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(25),
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(76),
blurRadius: 8,
offset: Offset(2, 2),
),
],
),
markdownStyle: getLlmChatMarkdownStyle(context),
),
// User Chat Style
userMessageStyle: UserMessageStyle(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25),
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(76),
blurRadius: 8,
offset: Offset(2, 2),
),
],
),
textStyle: TextStyle(
fontSize: 16,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
// User Input Style
chatInputStyle: ChatInputStyle(
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(76),
blurRadius: 8,
offset: Offset(2, 2),
),
],
),
hintStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
hintText: "Ask Mzansi AI...",
),
// Suggestions Style
suggestionStyle: SuggestionStyle(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(25),
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(76),
blurRadius: 8,
offset: Offset(2, 2),
),
],
),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
copyButtonStyle: ActionButtonStyle(
iconColor: MihColors.getSecondaryInvertedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
editButtonStyle: ActionButtonStyle(
iconColor: MihColors.getSecondaryInvertedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
cancelButtonStyle: ActionButtonStyle(
iconDecoration: BoxDecoration(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25),
),
iconColor: MihColors.getSecondaryInvertedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
);
}
}

View File

@@ -0,0 +1,141 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:ollama_dart/ollama_dart.dart';
class OllamaProvider extends LlmProvider with ChangeNotifier {
OllamaProvider({
String? baseUrl,
Map<String, String>? headers,
Map<String, String>? queryParams,
required String model,
String? systemPrompt,
}) : _client = OllamaClient(
baseUrl: baseUrl,
headers: headers,
queryParams: queryParams,
),
_model = model,
_systemPrompt = systemPrompt,
_history = [];
final OllamaClient _client;
final String _model;
final List<ChatMessage> _history;
final String? _systemPrompt;
@override
Stream<String> generateStream(
String prompt, {
Iterable<Attachment> attachments = const [],
}) async* {
final messages = _mapToOllamaMessages([
ChatMessage.user(prompt, attachments),
]);
yield* _generateStream(messages);
}
@override
Stream<String> sendMessageStream(
String prompt, {
Iterable<Attachment> attachments = const [],
}) async* {
KenLogger.success("sendMessageStream called with: $prompt");
final userMessage = ChatMessage.user(prompt, attachments);
final llmMessage = ChatMessage.llm();
_history.addAll([userMessage, llmMessage]);
notifyListeners();
KenLogger.success("History after adding messages: ${_history.length}");
final messages = _mapToOllamaMessages(_history);
final stream = _generateStream(messages);
yield* stream.map((chunk) {
llmMessage.append(chunk);
notifyListeners();
return chunk;
});
KenLogger.success("Stream completed for: $prompt");
notifyListeners();
}
@override
Iterable<ChatMessage> get history => _history;
void resetChat() {
_history.clear();
notifyListeners();
}
@override
set history(Iterable<ChatMessage> history) {
_history.clear();
_history.addAll(history);
notifyListeners();
}
Stream<String> _generateStream(List<Message> messages) async* {
final allMessages = <Message>[];
if (_systemPrompt != null && _systemPrompt.isNotEmpty) {
allMessages.add(Message(
role: MessageRole.system,
content: _systemPrompt,
));
}
allMessages.addAll(messages);
final stream = _client.generateChatCompletionStream(
request: GenerateChatCompletionRequest(
model: _model,
messages: allMessages,
),
);
// final stream = _client.generateChatCompletionStream(
// request: GenerateChatCompletionRequest(
// model: _model,
// messages: messages,
// ),
// );
yield* stream.map((res) => res.message.content);
}
List<Message> _mapToOllamaMessages(List<ChatMessage> messages) {
return messages.map((message) {
switch (message.origin) {
case MessageOrigin.user:
if (message.attachments.isEmpty) {
return Message(
role: MessageRole.user,
content: message.text ?? '',
);
}
return Message(
role: MessageRole.user,
content: message.text ?? '',
images: [
for (final attachment in message.attachments)
if (attachment is ImageFileAttachment)
base64Encode(attachment.bytes)
else
throw LlmFailureException(
'Unsupported attachment type: $attachment',
),
],
);
case MessageOrigin.llm:
return Message(
role: MessageRole.assistant,
content: message.text ?? '',
);
}
}).toList(growable: false);
}
@override
void dispose() {
_client.endSession();
super.dispose();
}
}

View File

@@ -1,27 +1,44 @@
import 'package:flutter/material.dart';
class MihColors {
bool women4Change = true;
static Color getPrimaryColor(bool darkMode) {
if (darkMode == true) {
return const Color(0XFF3A4454);
// return const Color(0XFF3A4454); // Original
return const Color(0XFF6641b2); // Women4change
} else {
return const Color(0XFFbedcfe);
// return const Color(0XFFbedcfe); // Original
return const Color(0xFFE0D1FF); // Women4change
}
}
static Color getSecondaryColor(bool darkMode) {
if (darkMode == true) {
return const Color(0XFFbedcfe);
// return const Color(0XFFbedcfe); // Original
return const Color(0xFFE0D1FF); // Women4change
} else {
return const Color(0XFF3A4454);
// return const Color(0XFF3A4454); // Original
return const Color(0XFF6641b2); // Women4change
}
}
static Color getSecondaryInvertedColor(bool darkMode) {
if (darkMode == true) {
// return const Color(0XFF412301); // Original
return const Color(0XFF1f2e00); // Women4change
} else {
// return const Color(0XFFc5bbab); // Original
return const Color(0XFF99be4d); // Women4change
}
}
static Color getHighlightColor(bool darkMode) {
if (darkMode == true) {
return const Color(0XFF9bc7fa);
// return const Color(0XFF9bc7fa);
return const Color(0xFFC8AFFB); // Women4change
} else {
return const Color(0XFF354866);
// return const Color(0XFF354866);
return const Color(0XFF6641b2); // Women4change
}
}

View File

@@ -14,7 +14,7 @@ class MihTheme {
late String loadingAssetText;
late TargetPlatform platform;
bool kIsWeb = const bool.fromEnvironment('dart.library.js_util');
String latestVersion = "1.2.2";
String latestVersion = "1.2.3";
// Options:-
// f3f9d2 = Cream
// f0f0c9 = cream2
@@ -35,48 +35,116 @@ class MihTheme {
ThemeData getData(bool bool) {
return ThemeData(
fontFamily: 'Segoe UI',
scaffoldBackgroundColor: MihColors.getPrimaryColor(mode == "Dark"),
// pageTransitionsTheme: PageTransitionsTheme(
// builders: Map<TargetPlatform, PageTransitionsBuilder>.fromIterable(
// TargetPlatform.values,
// value: (dynamic _) => const FadeUpwardsPageTransitionsBuilder(),
// ),
// ),
colorScheme: ColorScheme(
brightness: getBritness(),
primary: MihColors.getSecondaryColor(mode == "Dark"),
onPrimary: MihColors.getPrimaryColor(mode == "Dark"),
secondary: MihColors.getPrimaryColor(mode == "Dark"),
onSecondary: MihColors.getSecondaryColor(mode == "Dark"),
error: MihColors.getRedColor(mode == "Dark"),
onError: MihColors.getPrimaryColor(mode == "Dark"),
surface: MihColors.getPrimaryColor(mode == "Dark"),
onSurface: MihColors.getSecondaryColor(mode == "Dark"),
fontFamily: 'Segoe UI',
scaffoldBackgroundColor: MihColors.getPrimaryColor(mode == "Dark"),
// pageTransitionsTheme: PageTransitionsTheme(
// builders: Map<TargetPlatform, PageTransitionsBuilder>.fromIterable(
// TargetPlatform.values,
// value: (dynamic _) => const FadeUpwardsPageTransitionsBuilder(),
// ),
// ),
colorScheme: ColorScheme(
brightness: getBritness(),
primary: MihColors.getSecondaryColor(mode == "Dark"),
onPrimary: MihColors.getPrimaryColor(mode == "Dark"),
secondary: MihColors.getPrimaryColor(mode == "Dark"),
onSecondary: MihColors.getSecondaryColor(mode == "Dark"),
error: MihColors.getRedColor(mode == "Dark"),
onError: MihColors.getPrimaryColor(mode == "Dark"),
surface: MihColors.getPrimaryColor(mode == "Dark"),
onSurface: MihColors.getSecondaryColor(mode == "Dark"),
),
datePickerTheme: DatePickerThemeData(
backgroundColor: MihColors.getPrimaryColor(mode == "Dark"),
headerBackgroundColor: MihColors.getSecondaryColor(mode == "Dark"),
headerForegroundColor: MihColors.getPrimaryColor(mode == "Dark"),
),
appBarTheme: AppBarTheme(
color: MihColors.getSecondaryColor(mode == "Dark"),
foregroundColor: MihColors.getPrimaryColor(mode == "Dark"),
titleTextStyle: TextStyle(
color: MihColors.getPrimaryColor(mode == "Dark"),
fontSize: 25,
fontWeight: FontWeight.bold,
),
datePickerTheme: DatePickerThemeData(
backgroundColor: MihColors.getPrimaryColor(mode == "Dark"),
headerBackgroundColor: MihColors.getSecondaryColor(mode == "Dark"),
headerForegroundColor: MihColors.getPrimaryColor(mode == "Dark"),
),
appBarTheme: AppBarTheme(
),
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: MihColors.getSecondaryColor(mode == "Dark"),
foregroundColor: MihColors.getPrimaryColor(mode == "Dark"),
extendedTextStyle:
TextStyle(color: MihColors.getPrimaryColor(mode == "Dark")),
),
drawerTheme: DrawerThemeData(
backgroundColor: MihColors.getPrimaryColor(mode == "Dark"),
),
// Text selection / cursor color
textSelectionTheme: TextSelectionThemeData(
cursorColor: MihColors.getPrimaryColor(mode == "Dark"),
selectionColor:
MihColors.getPrimaryColor(mode == "Dark").withOpacity(0.25),
selectionHandleColor: MihColors.getPrimaryColor(mode == "Dark"),
),
tooltipTheme: TooltipThemeData(
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(mode == "Dark"),
foregroundColor: MihColors.getPrimaryColor(mode == "Dark"),
titleTextStyle: TextStyle(
borderRadius: BorderRadius.circular(6),
border: Border.all(
width: 1.0,
color: MihColors.getPrimaryColor(mode == "Dark"),
fontSize: 25,
fontWeight: FontWeight.bold,
),
boxShadow: [
BoxShadow(
color:
MihColors.getPrimaryColor(mode == "Dark").withOpacity(0.18),
blurRadius: 6,
offset: const Offset(0, 2),
),
],
),
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: MihColors.getSecondaryColor(mode == "Dark"),
foregroundColor: MihColors.getPrimaryColor(mode == "Dark"),
extendedTextStyle:
TextStyle(color: MihColors.getPrimaryColor(mode == "Dark")),
textStyle: TextStyle(
color: MihColors.getPrimaryColor(mode == "Dark"),
fontSize: 13,
height: 1.2,
),
drawerTheme: DrawerThemeData(
backgroundColor: MihColors.getPrimaryColor(mode == "Dark"),
));
waitDuration: const Duration(milliseconds: 500),
showDuration: const Duration(seconds: 3),
preferBelow: true,
verticalOffset: 24,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
triggerMode: TooltipTriggerMode.longPress,
),
// // Input decoration (text fields) theme
// inputDecorationTheme: InputDecorationTheme(
// filled: true,
// fillColor: mode == "Dark"
// ? MihColors.getPrimaryColor(true).withOpacity(0.06)
// : MihColors.getPrimaryColor(false).withOpacity(0.03),
// contentPadding:
// const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(8),
// borderSide:
// BorderSide(color: MihColors.getSecondaryColor(mode == "Dark")),
// ),
// enabledBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(8),
// borderSide: BorderSide(
// color:
// MihColors.getSecondaryColor(mode == "Dark").withOpacity(0.6)),
// ),
// focusedBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(8),
// borderSide: BorderSide(
// color: MihColors.getSecondaryColor(mode == "Dark"), width: 2),
// ),
// hintStyle: TextStyle(
// color:
// MihColors.getSecondaryColor(mode == "Dark").withOpacity(0.7)),
// labelStyle:
// TextStyle(color: MihColors.getSecondaryColor(mode == "Dark")),
// errorStyle: TextStyle(color: MihColors.getRedColor(mode == "Dark")),
// ),
);
}
String getPlatform() {
@@ -165,65 +233,65 @@ class MihTheme {
// }
// }
AssetImage loadingImage() {
if (mode == "Dark") {
loading = const AssetImage(
'lib/mih_components/mih_package_components/assets/images/loading_light.gif',
);
} else {
loading = const AssetImage(
'lib/mih_components/mih_package_components/assets/images/loading_dark.gif',
);
}
return loading;
}
// AssetImage loadingImage() {
// if (mode == "Dark") {
// loading = const AssetImage(
// 'lib/mih_components/mih_package_components/assets/images/loading_light.gif',
// );
// } else {
// loading = const AssetImage(
// 'lib/mih_components/mih_package_components/assets/images/loading_dark.gif',
// );
// }
// return loading;
// }
AssetImage altLoadingImage() {
if (mode == "Dark") {
loading = const AssetImage(
'lib/mih_components/mih_package_components/assets/images/loading_dark.gif',
);
} else {
loading = const AssetImage(
'lib/mih_components/mih_package_components/assets/images/loading_light.gif',
);
}
return loading;
}
// AssetImage altLoadingImage() {
// if (mode == "Dark") {
// loading = const AssetImage(
// 'lib/mih_components/mih_package_components/assets/images/loading_dark.gif',
// );
// } else {
// loading = const AssetImage(
// 'lib/mih_components/mih_package_components/assets/images/loading_light.gif',
// );
// }
// return loading;
// }
String loadingImageLocation() {
if (mode == "Dark") {
loadingAssetText =
'lib/mih_components/mih_package_components/assets/images/loading_light.gif';
} else {
loadingAssetText =
'lib/mih_components/mih_package_components/assets/images/loading_dark.gif';
}
return loadingAssetText;
}
// String loadingImageLocation() {
// if (mode == "Dark") {
// loadingAssetText =
// 'lib/mih_components/mih_package_components/assets/images/loading_light.gif';
// } else {
// loadingAssetText =
// 'lib/mih_components/mih_package_components/assets/images/loading_dark.gif';
// }
// return loadingAssetText;
// }
String altLoadingImageLocation() {
if (mode == "Dark") {
loadingAssetText =
'lib/mih_components/mih_package_components/assets/images/loading_dark.gif';
} else {
loadingAssetText =
'lib/mih_components/mih_package_components/assets/images/loading_light.gif';
}
return loadingAssetText;
}
// String altLoadingImageLocation() {
// if (mode == "Dark") {
// loadingAssetText =
// 'lib/mih_components/mih_package_components/assets/images/loading_dark.gif';
// } else {
// loadingAssetText =
// 'lib/mih_components/mih_package_components/assets/images/loading_light.gif';
// }
// return loadingAssetText;
// }
AssetImage aiLogoImage() {
if (mode == "Dark") {
return const AssetImage(
'lib/mih_components/mih_package_components/assets/images/mzansi_ai-dark.png',
);
} else {
return const AssetImage(
'lib/mih_components/mih_package_components/assets/images/mzansi_ai-light.png',
);
}
}
// AssetImage aiLogoImage() {
// if (mode == "Dark") {
// return const AssetImage(
// 'lib/mih_components/mih_package_components/assets/images/mzansi_ai-dark.png',
// );
// } else {
// return const AssetImage(
// 'lib/mih_components/mih_package_components/assets/images/mzansi_ai-light.png',
// );
// }
// }
void setScreenType(double width) {
if (width <= 800) {

View File

@@ -161,7 +161,6 @@ class _MihInfoState extends State<MihInfo> {
String heading = "Our Mission";
String mission =
"Bridge the digital divide in Mzansi, ensuring that everyone can benefit from the power of technology. We empower lives by providing simple, elegant solutions that elevate daily experiences. With our user-friendly approach, we're making the digital world accessible to all, ensuring no one is left behind in the digital revolution.";
return SizedBox(
width: 500,
child: Column(
@@ -191,6 +190,118 @@ class _MihInfoState extends State<MihInfo> {
);
}
Widget womenForChange() {
String heading = "MIH Stands with Women For Change SA";
String mission =
"South Africa is facing a devastating crisis of Gender-Based Violence and Femicide (GBVF), with at least 15 women murdered and 117 women reporting rape daily, often at the hands of known individuals, as highlighted by a shocking 33.8% rise in femicide in the last year, despite the existence of the National Strategic Plan on GBVF (NSP GBVF). Due to the government's lack of urgent action and funding for the NSP GBVF's implementation, organizations like Women For Change are urgently calling for the immediate declaration of GBVF as a National Disaster to mobilize resources and political will for decisive action, which must include judicial reforms (like opposing bail and implementing harsher sentences), immediate funding of the NSP GBVF and the new National Council, making the National Sex Offenders Register publicly accessible, and mandating comprehensive GBVF education and continuous public awareness campaigns.";
return SizedBox(
width: 500,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
heading,
textAlign: TextAlign.center,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
const SizedBox(
height: 10,
),
Wrap(
alignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 10,
runSpacing: 10,
children: [
MihButton(
onPressed: () {
launchSocialUrl(
Uri.parse(
"https://www.tiktok.com/@womenforchange.sa",
),
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FaIcon(
FontAwesomeIcons.tiktok,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(width: 10),
Text(
"@womenforchange.sa",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
),
),
MihButton(
onPressed: () {
launchSocialUrl(
Uri.parse(
"https://www.change.org/p/declare-gbvf-a-national-disaster-in-south-africa",
),
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FaIcon(
Icons.edit,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(width: 10),
Text(
"Sign Petition",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
),
const SizedBox(
height: 10,
),
Text(
mission,
textAlign: TextAlign.center,
style: const TextStyle(
//fontWeight: FontWeight.bold,
fontSize: 17,
),
),
],
),
);
}
Widget mihSocials() {
String heading = "Follow Our Journey";
return Column(
@@ -736,6 +847,7 @@ class _MihInfoState extends State<MihInfo> {
spacing: 10,
runSpacing: 10,
children: [
womenForChange(),
ourVision(),
ourMission(),
],

View File

@@ -227,11 +227,11 @@ class _MihBusinessHomeState extends State<MihBusinessHome>
hintColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onPrefixIconTap: () {
mzansiAiProvider
.setStartUpQuestion(searchController.text);
context.goNamed(
"mzansiAi",
);
if (searchController.text.isNotEmpty) {
mzansiAiProvider
.setStartUpQuestion(searchController.text);
}
context.goNamed("mzansiAi");
searchController.clear();
},
searchFocusNode: _searchFocusNode,

View File

@@ -286,11 +286,11 @@ class _MihPersonalHomeState extends State<MihPersonalHome>
hintColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onPrefixIconTap: () {
mzansiAiProvider
.setStartUpQuestion(searchController.text);
context.goNamed(
"mzansiAi",
);
if (searchController.text.isNotEmpty) {
mzansiAiProvider
.setStartUpQuestion(searchController.text);
}
context.goNamed("mzansiAi");
searchController.clear();
},
searchFocusNode: _searchFocusNode,

View File

@@ -3,8 +3,8 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tools/ai_chat.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tools/mih_ai_chat.dart';
import 'package:provider/provider.dart';
class MzansiAi extends StatefulWidget {
@@ -36,6 +36,9 @@ class _MzansiAiState extends State<MzansiAi> {
temp[const Icon(Icons.chat)] = () {
context.read<MzansiAiProvider>().setToolIndex(0);
};
// temp[const Icon(Icons.chat)] = () {
// context.read<MzansiAiProvider>().setToolIndex(1);
// };
return MihPackageTools(
tools: temp,
@@ -45,7 +48,8 @@ class _MzansiAiState extends State<MzansiAi> {
List<Widget> getToolBody() {
List<Widget> toolBodies = [
AiChat(),
// AiChat(),
MihAiChat(),
];
return toolBodies;
}
@@ -53,6 +57,7 @@ class _MzansiAiState extends State<MzansiAi> {
List<String> getToolTitle() {
List<String> toolTitles = [
"Ask Mzansi",
// "New Chat",
];
return toolTitles;
}

View File

@@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:gpt_markdown/gpt_markdown.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart';
@@ -223,8 +222,21 @@ class _AiChatState extends State<AiChat> {
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
// SelectionArea(
// child: GptMarkdown(
// snapshot.requireData,
// textAlign: TextAlign.left,
// style: TextStyle(
// color: MihColors.getSecondaryColor(
// MzansiInnovationHub.of(context)!.theme.mode ==
// "Dark"),
// fontSize: _chatFrontSize,
// fontWeight: FontWeight.bold,
// ),
// ),
// ),
SelectionArea(
child: GptMarkdown(
child: Text(
snapshot.requireData,
textAlign: TextAlign.left,
style: TextStyle(
@@ -600,9 +612,6 @@ class _AiChatState extends State<AiChat> {
_voicesString =
_voices.map((_voice) => _voice["name"] as String).toList();
_voicesString.sort();
// print(
// "=================== Voices ===================\n$_voicesString");
setTtsVoice(_voicesString.first);
});
} catch (e) {

View File

@@ -0,0 +1,294 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:flutter_tts/flutter_tts.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:provider/provider.dart';
class MihAiChat extends StatefulWidget {
const MihAiChat({super.key});
@override
State<MihAiChat> createState() => _MihAiChatState();
}
class _MihAiChatState extends State<MihAiChat> {
final FlutterTts _flutterTts = FlutterTts();
Widget noMessagescDisplay() {
return Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.mzansiAi,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"Mzansi AI is here to help",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
const SizedBox(height: 25),
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
children: [
TextSpan(
text:
"Send us a message and we'll try our best to assist you"),
],
),
),
),
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
children: [
TextSpan(text: "Press "),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Icon(
Icons.menu,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
TextSpan(text: " to start a new chat or read last message"),
],
),
),
),
],
),
),
);
}
void resetChat(MzansiAiProvider aiProvider) {
aiProvider.ollamaProvider.resetChat();
}
void speakLastMessage(MzansiAiProvider aiProvider) {
final history = aiProvider.ollamaProvider.history;
if (history.isNotEmpty) {
final historyList = history.toList();
for (int i = historyList.length - 1; i >= 0; i--) {
if (historyList[i].origin == MessageOrigin.llm &&
historyList[i].text != null &&
historyList[i].text!.isNotEmpty) {
_flutterTts.speak(historyList[i].text!);
return;
}
}
}
}
void stopTTS(MzansiAiProvider aiProvider) {
_flutterTts.stop();
aiProvider.setTTSstate(false);
}
Future<void> initTts(MzansiAiProvider aiProvider) async {
try {
await _flutterTts.setSpeechRate(!kIsWeb ? 0.55 : 1);
// await _flutterTts.setLanguage("en-US");
// Safer voice selection with error handling
_flutterTts.getVoices.then((data) {
try {
final voices = List<Map>.from(data);
final englishVoices = voices.where((voice) {
final name = voice["name"]?.toString().toLowerCase() ?? '';
final locale = voice["locale"]?.toString().toLowerCase() ?? '';
return name.contains("en-us") || locale.contains("en_us");
}).toList();
if (englishVoices.isNotEmpty) {
// Use the first available English voice
_flutterTts.setVoice({"name": englishVoices.first["name"]});
}
// If no voices found, use default
} catch (e) {
KenLogger.error("Error setting TTS voice: $e");
}
});
} catch (e) {
KenLogger.error("Error initializing TTS: $e");
}
_flutterTts.setStartHandler(() {
if (mounted) {
aiProvider.setTTSstate(true);
}
});
_flutterTts.setCompletionHandler(() {
if (mounted) {
aiProvider.setTTSstate(false);
}
});
_flutterTts.setErrorHandler((message) {
if (mounted) {
aiProvider.setTTSstate(false);
}
});
}
void initStartQuestion() {
WidgetsBinding.instance.addPostFrameCallback((_) async {
final mzansiAiProvider = context.read<MzansiAiProvider>();
final startQuestion = mzansiAiProvider.startUpQuestion;
if (startQuestion != null && startQuestion.isNotEmpty) {
final stream =
mzansiAiProvider.ollamaProvider.sendMessageStream(startQuestion);
stream.listen((chunk) {});
mzansiAiProvider.clearStartUpQuestion();
}
});
}
@override
void initState() {
super.initState();
MzansiAiProvider aiProvider = context.read<MzansiAiProvider>();
initTts(aiProvider);
initStartQuestion();
}
@override
void dispose() {
_flutterTts.stop();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Consumer<MzansiAiProvider>(
builder:
(BuildContext context, MzansiAiProvider aiProvider, Widget? child) {
bool hasHistory = aiProvider.ollamaProvider.history.isNotEmpty;
String? lastMessage;
if (hasHistory) {
final histroyList = aiProvider.ollamaProvider.history.toList();
lastMessage = histroyList[histroyList.length - 1].text;
}
return Stack(
children: [
LlmChatView(
provider: aiProvider.ollamaProvider,
messageSender: aiProvider.ollamaProvider.sendMessageStream,
// welcomeMessage:
// "Mzansi AI is here to help. Send us a messahe and we'll try our best to assist you.",
autofocus: false,
enableAttachments: false,
enableVoiceNotes: false,
style: aiProvider.getChatStyle(context),
suggestions: [
"What is mih all about?",
"What are the features of MIH?"
],
),
if (hasHistory && lastMessage != null)
Positioned(
bottom: 80,
left: 10,
child: MihButton(
width: 35,
height: 35,
onPressed: () {
if (!aiProvider.ttsOn) {
speakLastMessage(aiProvider);
} else {
stopTTS(aiProvider);
}
},
buttonColor: !aiProvider.ttsOn
? MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
child: Icon(
!aiProvider.ttsOn ? Icons.volume_up : Icons.volume_off,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
),
Positioned(
right: 10,
bottom: 80,
child: MihFloatingMenu(
animatedIcon: AnimatedIcons.menu_close,
children: [
SpeedDialChild(
child: Icon(
Icons.refresh,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
label: "New Chat",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
resetChat(aiProvider);
},
),
],
),
),
if (!hasHistory) noMessagescDisplay(),
],
);
},
);
}
}

View File

@@ -7,16 +7,24 @@
#include "generated_plugin_registrant.h"
#include <file_saver/file_saver_plugin.h>
#include <file_selector_linux/file_selector_plugin.h>
#include <printing/printing_plugin.h>
#include <record_linux/record_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_saver_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSaverPlugin");
file_saver_plugin_register_with_registrar(file_saver_registrar);
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) printing_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "PrintingPlugin");
printing_plugin_register_with_registrar(printing_registrar);
g_autoptr(FlPluginRegistrar) record_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "RecordLinuxPlugin");
record_linux_plugin_register_with_registrar(record_linux_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);

View File

@@ -4,7 +4,9 @@
list(APPEND FLUTTER_PLUGIN_LIST
file_saver
file_selector_linux
printing
record_linux
url_launcher_linux
)

View File

@@ -9,6 +9,10 @@ import app_settings
import device_info_plus
import file_picker
import file_saver
import file_selector_macos
import firebase_app_check
import firebase_auth
import firebase_core
import flutter_tts
import geolocator_apple
import local_auth_darwin
@@ -16,9 +20,11 @@ import mobile_scanner
import package_info_plus
import path_provider_foundation
import printing
import record_macos
import screen_brightness_macos
import share_plus
import shared_preferences_foundation
import speech_to_text
import sqflite_darwin
import syncfusion_pdfviewer_macos
import url_launcher_macos
@@ -29,6 +35,10 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FLTFirebaseAppCheckPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAppCheckPlugin"))
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
FLALocalAuthPlugin.register(with: registry.registrar(forPlugin: "FLALocalAuthPlugin"))
@@ -36,9 +46,11 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
PrintingPlugin.register(with: registry.registrar(forPlugin: "PrintingPlugin"))
RecordMacOsPlugin.register(with: registry.registrar(forPlugin: "RecordMacOsPlugin"))
ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SpeechToTextPlugin.register(with: registry.registrar(forPlugin: "SpeechToTextPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
SyncfusionFlutterPdfViewerPlugin.register(with: registry.registrar(forPlugin: "SyncfusionFlutterPdfViewerPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -9,6 +9,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "82.0.0"
_flutterfire_internals:
dependency: transitive
description:
name: _flutterfire_internals
sha256: "8a1f5f3020ef2a74fb93f7ab3ef127a8feea33a7a2276279113660784ee7516a"
url: "https://pub.dev"
source: hosted
version: "1.3.64"
analyzer:
dependency: transitive
description:
@@ -201,6 +209,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
camera:
dependency: transitive
description:
name: camera
sha256: "87a27e0553e3432119c1c2f6e4b9a1bbf7d2c660552b910bfa59185a9facd632"
url: "https://pub.dev"
source: hosted
version: "0.11.2+1"
camera_android_camerax:
dependency: transitive
description:
name: camera_android_camerax
sha256: "58b8fe843a3c83fd1273c00cb35f5a8ae507f6cc9b2029bcf7e2abba499e28d8"
url: "https://pub.dev"
source: hosted
version: "0.6.19+1"
camera_avfoundation:
dependency: transitive
description:
name: camera_avfoundation
sha256: "951ef122d01ebba68b7a54bfe294e8b25585635a90465c311b2f875ae72c412f"
url: "https://pub.dev"
source: hosted
version: "0.9.21+2"
camera_platform_interface:
dependency: transitive
description:
name: camera_platform_interface
sha256: "98cfc9357e04bad617671b4c1f78a597f25f08003089dd94050709ae54effc63"
url: "https://pub.dev"
source: hosted
version: "2.12.0"
camera_web:
dependency: transitive
description:
name: camera_web
sha256: "595f28c89d1fb62d77c73c633193755b781c6d2e0ebcd8dc25b763b514e6ba8f"
url: "https://pub.dev"
source: hosted
version: "0.3.5"
characters:
dependency: transitive
description:
@@ -385,22 +433,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.3"
fetch_api:
dependency: transitive
description:
name: fetch_api
sha256: "24cbd5616f3d4008c335c197bb90bfa0eb43b9e55c6de5c60d1f805092636034"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
fetch_client:
dependency: transitive
description:
name: fetch_client
sha256: "375253f4efe64303c793fb17fe90771c591320b2ae11fb29cb5b406cc8533c00"
url: "https://pub.dev"
source: hosted
version: "1.1.4"
ffi:
dependency: transitive
description:
@@ -433,6 +465,150 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.3.1"
file_selector:
dependency: transitive
description:
name: file_selector
sha256: "5f1d15a7f17115038f433d1b0ea57513cc9e29a9d5338d166cb0bef3fa90a7a0"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
file_selector_android:
dependency: transitive
description:
name: file_selector_android
sha256: "1ce58b609289551f8ec07265476720e77d19764339cc1d8e4df3c4d34dac6499"
url: "https://pub.dev"
source: hosted
version: "0.5.1+17"
file_selector_ios:
dependency: transitive
description:
name: file_selector_ios
sha256: fe9f52123af16bba4ad65bd7e03defbbb4b172a38a8e6aaa2a869a0c56a5f5fb
url: "https://pub.dev"
source: hosted
version: "0.5.3+2"
file_selector_linux:
dependency: transitive
description:
name: file_selector_linux
sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33"
url: "https://pub.dev"
source: hosted
version: "0.9.3+2"
file_selector_macos:
dependency: transitive
description:
name: file_selector_macos
sha256: "19124ff4a3d8864fdc62072b6a2ef6c222d55a3404fe14893a3c02744907b60c"
url: "https://pub.dev"
source: hosted
version: "0.9.4+4"
file_selector_platform_interface:
dependency: transitive
description:
name: file_selector_platform_interface
sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b
url: "https://pub.dev"
source: hosted
version: "2.6.2"
file_selector_web:
dependency: transitive
description:
name: file_selector_web
sha256: c4c0ea4224d97a60a7067eca0c8fd419e708ff830e0c83b11a48faf566cec3e7
url: "https://pub.dev"
source: hosted
version: "0.9.4+2"
file_selector_windows:
dependency: transitive
description:
name: file_selector_windows
sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b"
url: "https://pub.dev"
source: hosted
version: "0.9.3+4"
firebase_ai:
dependency: transitive
description:
name: firebase_ai
sha256: "6bffa52bc4b9557b73f59de12ec36349bde76f772431d0702c7ecb4bfeeeb21b"
url: "https://pub.dev"
source: hosted
version: "3.5.0"
firebase_app_check:
dependency: transitive
description:
name: firebase_app_check
sha256: "4d00b502f510ee97cdb395e95a31a8b871fc96cb917ffc60591528d3c9735986"
url: "https://pub.dev"
source: hosted
version: "0.4.1+2"
firebase_app_check_platform_interface:
dependency: transitive
description:
name: firebase_app_check_platform_interface
sha256: "7d104d01b00e5dec367dc79184ad99bd1941f2d839b5ef41156b2330c18af13f"
url: "https://pub.dev"
source: hosted
version: "0.2.1+2"
firebase_app_check_web:
dependency: transitive
description:
name: firebase_app_check_web
sha256: "885a1a7b8e33c52afaf9c5d75eca616ae310d6ea90322e9a462f8c154ad16b64"
url: "https://pub.dev"
source: hosted
version: "0.2.2"
firebase_auth:
dependency: transitive
description:
name: firebase_auth
sha256: e54fb3ba57de041d832574126a37726eedf0f57400869f1942b0ca8ce4a6e209
url: "https://pub.dev"
source: hosted
version: "6.1.2"
firebase_auth_platform_interface:
dependency: transitive
description:
name: firebase_auth_platform_interface
sha256: "421f95dc553cb283ed9d4d140e719800c0331d49ed37b962e513c9d1d61b090b"
url: "https://pub.dev"
source: hosted
version: "8.1.4"
firebase_auth_web:
dependency: transitive
description:
name: firebase_auth_web
sha256: a064ffee202f7d42d62e2c01775899d4ffcb83c602af07632f206acd46a0964e
url: "https://pub.dev"
source: hosted
version: "6.1.0"
firebase_core:
dependency: transitive
description:
name: firebase_core
sha256: "1f2dfd9f535d81f8b06d7a50ecda6eac1e6922191ed42e09ca2c84bd2288927c"
url: "https://pub.dev"
source: hosted
version: "4.2.1"
firebase_core_platform_interface:
dependency: transitive
description:
name: firebase_core_platform_interface
sha256: cccb4f572325dc14904c02fcc7db6323ad62ba02536833dddb5c02cac7341c64
url: "https://pub.dev"
source: hosted
version: "6.0.2"
firebase_core_web:
dependency: transitive
description:
name: firebase_core_web
sha256: ff18fabb0ad0ed3595d2f2c85007ecc794aadecdff5b3bb1460b7ee47cded398
url: "https://pub.dev"
source: hosted
version: "3.3.0"
fixnum:
dependency: transitive
description:
@@ -454,6 +630,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_ai_toolkit:
dependency: "direct main"
description:
name: flutter_ai_toolkit
sha256: b653814f9aac05d84f15db0daf1bf90e9bd9177abeba378c6f1d4a75bb2099a5
url: "https://pub.dev"
source: hosted
version: "0.10.0"
flutter_cache_manager:
dependency: transitive
description:
@@ -478,6 +662,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.6.15"
flutter_context_menu:
dependency: transitive
description:
name: flutter_context_menu
sha256: "79fe00cd7e3ac3840a552cb3e653d8eb61d827b6c04c559e219973a1dc769165"
url: "https://pub.dev"
source: hosted
version: "0.3.0"
flutter_launcher_icons:
dependency: "direct main"
description:
@@ -510,14 +702,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.0.0"
flutter_math_fork:
dependency: transitive
flutter_markdown_plus:
dependency: "direct main"
description:
name: flutter_math_fork
sha256: "6d5f2f1aa57ae539ffb0a04bb39d2da67af74601d685a161aff7ce5bda5fa407"
name: flutter_markdown_plus
sha256: "7f349c075157816da399216a4127096108fd08e1ac931e34e72899281db4113c"
url: "https://pub.dev"
source: hosted
version: "0.7.4"
version: "1.0.5"
flutter_native_splash:
dependency: "direct main"
description:
@@ -534,6 +726,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.1"
flutter_picture_taker:
dependency: transitive
description:
name: flutter_picture_taker
sha256: d24d4c10e42324832b550bd59d1fe84129e860b75b4b2d57d6b398a41fd5dc9a
url: "https://pub.dev"
source: hosted
version: "0.2.0"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
@@ -588,10 +788,10 @@ packages:
dependency: transitive
description:
name: freezed_annotation
sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2
sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8"
url: "https://pub.dev"
source: hosted
version: "2.4.4"
version: "3.1.0"
frontend_server_client:
dependency: transitive
description:
@@ -648,14 +848,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.2.5"
gif_view:
dependency: "direct main"
description:
name: gif_view
sha256: "4c7e17c134719531dabab54af121e4600d63283f56f3aff57c16db54766b67bc"
url: "https://pub.dev"
source: hosted
version: "1.0.3"
glob:
dependency: transitive
description:
@@ -680,6 +872,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "16.1.0"
google_fonts:
dependency: transitive
description:
name: google_fonts
sha256: "517b20870220c48752eafa0ba1a797a092fb22df0d89535fd9991e86ee2cdd9c"
url: "https://pub.dev"
source: hosted
version: "6.3.2"
google_mobile_ads:
dependency: "direct main"
description:
@@ -688,14 +888,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.0.0"
gpt_markdown:
dependency: "direct main"
description:
name: gpt_markdown
sha256: "68d5337c8a00fc03a37dbddf84a6fd90401c30e99b6baf497ef9522a81fc34ee"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
graphs:
dependency: transitive
description:
@@ -744,6 +936,70 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.5.4"
image_picker:
dependency: transitive
description:
name: image_picker
sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: "28f3987ca0ec702d346eae1d90eda59603a2101b52f1e234ded62cff1d5cfa6e"
url: "https://pub.dev"
source: hosted
version: "0.8.13+1"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e
url: "https://pub.dev"
source: hosted
version: "0.8.13"
image_picker_linux:
dependency: transitive
description:
name: image_picker_linux
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
url: "https://pub.dev"
source: hosted
version: "0.2.2"
image_picker_macos:
dependency: transitive
description:
name: image_picker_macos
sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04
url: "https://pub.dev"
source: hosted
version: "0.2.2"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c"
url: "https://pub.dev"
source: hosted
version: "2.11.1"
image_picker_windows:
dependency: transitive
description:
name: image_picker_windows
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
url: "https://pub.dev"
source: hosted
version: "0.2.2"
intl:
dependency: "direct main"
description:
@@ -872,6 +1128,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.0"
markdown:
dependency: transitive
description:
name: markdown
sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1"
url: "https://pub.dev"
source: hosted
version: "7.3.0"
matcher:
dependency: transitive
description:
@@ -956,10 +1220,10 @@ packages:
dependency: "direct main"
description:
name: ollama_dart
sha256: "4e40bc499b6fe46ba54a004d2da601c40bd73d66e3f18cf7b03225ccf3d481a6"
sha256: "55a45e381f3cf24791df510e287f353e776d376f556d34ba49b09bc918eee319"
url: "https://pub.dev"
source: hosted
version: "0.2.2+1"
version: "0.2.5"
os_detect:
dependency: transitive
description:
@@ -1072,6 +1336,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.4"
pedantic:
dependency: transitive
description:
name: pedantic
sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
petitparser:
dependency: transitive
description:
@@ -1176,6 +1448,102 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.2"
quick_actions:
dependency: "direct main"
description:
name: quick_actions
sha256: "7e35dd6a21f5bbd21acf6899039eaf85001a5ac26d52cbd6a8a2814505b90798"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
quick_actions_android:
dependency: transitive
description:
name: quick_actions_android
sha256: "612c9d53364c641ddcdeafed83c68fc14efb1bf4f686979d755024fc976fc888"
url: "https://pub.dev"
source: hosted
version: "1.0.23"
quick_actions_ios:
dependency: transitive
description:
name: quick_actions_ios
sha256: ee2cd54e3bd674eb031ca195b3b9974583638d141493aec1066dee3b2599ed08
url: "https://pub.dev"
source: hosted
version: "1.2.1"
quick_actions_platform_interface:
dependency: transitive
description:
name: quick_actions_platform_interface
sha256: "1fec7068db5122cd019e9340d3d7be5d36eab099695ef3402c7059ee058329a4"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
record:
dependency: transitive
description:
name: record
sha256: "6bad72fb3ea6708d724cf8b6c97c4e236cf9f43a52259b654efeb6fd9b737f1f"
url: "https://pub.dev"
source: hosted
version: "6.1.2"
record_android:
dependency: transitive
description:
name: record_android
sha256: fb54ee4e28f6829b8c580252a9ef49d9c549cfd263b0660ad7eeac0908658e9f
url: "https://pub.dev"
source: hosted
version: "1.4.4"
record_ios:
dependency: transitive
description:
name: record_ios
sha256: "765b42ac1be019b1674ddd809b811fc721fe5a93f7bb1da7803f0d16772fd6d7"
url: "https://pub.dev"
source: hosted
version: "1.1.4"
record_linux:
dependency: transitive
description:
name: record_linux
sha256: "235b1f1fb84e810f8149cc0c2c731d7d697f8d1c333b32cb820c449bf7bb72d8"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
record_macos:
dependency: transitive
description:
name: record_macos
sha256: "842ea4b7e95f4dd237aacffc686d1b0ff4277e3e5357865f8d28cd28bc18ed95"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
record_platform_interface:
dependency: transitive
description:
name: record_platform_interface
sha256: b0065fdf1ec28f5a634d676724d388a77e43ce7646fb049949f58c69f3fcb4ed
url: "https://pub.dev"
source: hosted
version: "1.4.0"
record_web:
dependency: transitive
description:
name: record_web
sha256: "20ac10d56514cb9f8cecc8f3579383084fdfb43b0d04e05a95244d0d76091d90"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
record_windows:
dependency: transitive
description:
name: record_windows
sha256: "223258060a1d25c62bae18282c16783f28581ec19401d17e56b5205b9f039d78"
url: "https://pub.dev"
source: hosted
version: "1.0.7"
redacted:
dependency: "direct main"
description:
@@ -1389,6 +1757,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.10.1"
speech_to_text:
dependency: "direct main"
description:
name: speech_to_text
sha256: c07557664974afa061f221d0d4186935bea4220728ea9446702825e8b988db04
url: "https://pub.dev"
source: hosted
version: "7.3.0"
speech_to_text_platform_interface:
dependency: transitive
description:
name: speech_to_text_platform_interface
sha256: a1935847704e41ee468aad83181ddd2423d0833abe55d769c59afca07adb5114
url: "https://pub.dev"
source: hosted
version: "2.3.0"
speech_to_text_windows:
dependency: transitive
description:
name: speech_to_text_windows
sha256: "2c9846d18253c7bbe059a276297ef9f27e8a2745dead32192525beb208195072"
url: "https://pub.dev"
source: hosted
version: "1.0.0+beta.8"
sprintf:
dependency: transitive
description:
@@ -1581,14 +1973,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.2"
tuple:
dependency: transitive
description:
name: tuple
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
url: "https://pub.dev"
source: hosted
version: "2.0.2"
typed_data:
dependency: transitive
description:
@@ -1613,6 +1997,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.2"
universal_platform:
dependency: transitive
description:
name: universal_platform
sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
upgrader:
dependency: "direct main"
description:
@@ -1757,6 +2149,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.1"
waveform_flutter:
dependency: transitive
description:
name: waveform_flutter
sha256: "08c9e98d4cf119428d8b3c083ed42c11c468623eaffdf30420ae38e36662922a"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
waveform_recorder:
dependency: transitive
description:
name: waveform_recorder
sha256: "1ca0a19b143d1bdef2adfb3d28f0627c18aee5285235c8cf81a89bf29a0420e1"
url: "https://pub.dev"
source: hosted
version: "1.8.0"
web:
dependency: transitive
description:

View File

@@ -1,7 +1,7 @@
name: mzansi_innovation_hub
description: ""
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.2.2+103
version: 1.2.3+112
# version: 1.1.1+97 #--- Updated version for upgrader package testing
environment:
@@ -22,7 +22,6 @@ dependencies:
supertokens_flutter: ^0.6.3
http: ^1.2.1
args: ^2.7.0
gif_view: ^1.0.3
intl: ^0.20.2
flutter_native_splash: ^2.4.6
printing: ^5.13.3
@@ -54,11 +53,14 @@ dependencies:
go_router: ^16.1.0
screen_brightness: ^2.1.6
cached_network_image: ^3.4.1
gpt_markdown: ^1.1.2
upgrader: ^12.0.0
screenshot: ^3.0.0
file_saver: ^0.3.1
provider: ^6.1.5+1
flutter_ai_toolkit: ^0.10.0
flutter_markdown_plus: ^1.0.5
speech_to_text: ^7.3.0
quick_actions: ^1.1.0
dev_dependencies:
flutter_test:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -3,8 +3,8 @@
"short_name": "MIH",
"start_url": ".",
"display": "standalone",
"background_color": "#3A4454",
"theme_color": "#3A4454",
"background_color": "#6641b2",
"theme_color": "#6641b2",
"description": "Digitizing Mzansi one process at a time. Discover essential Mzansi apps to streamline your personal and professional life. Simplify your daily tasks with our user-friendly solutions.",
"orientation": "any",
"prefer_related_applications": false,

View File

@@ -7,19 +7,30 @@
#include "generated_plugin_registrant.h"
#include <file_saver/file_saver_plugin.h>
#include <file_selector_windows/file_selector_windows.h>
#include <firebase_auth/firebase_auth_plugin_c_api.h>
#include <firebase_core/firebase_core_plugin_c_api.h>
#include <fl_downloader/fl_downloader_plugin_c_api.h>
#include <flutter_tts/flutter_tts_plugin.h>
#include <geolocator_windows/geolocator_windows.h>
#include <local_auth_windows/local_auth_plugin.h>
#include <printing/printing_plugin.h>
#include <record_windows/record_windows_plugin_c_api.h>
#include <screen_brightness_windows/screen_brightness_windows_plugin.h>
#include <share_plus/share_plus_windows_plugin_c_api.h>
#include <speech_to_text_windows/speech_to_text_windows.h>
#include <syncfusion_pdfviewer_windows/syncfusion_pdfviewer_windows_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FileSaverPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSaverPlugin"));
FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows"));
FirebaseAuthPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi"));
FirebaseCorePluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
FlDownloaderPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlDownloaderPluginCApi"));
FlutterTtsPluginRegisterWithRegistrar(
@@ -30,10 +41,14 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
PrintingPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PrintingPlugin"));
RecordWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("RecordWindowsPluginCApi"));
ScreenBrightnessWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenBrightnessWindowsPlugin"));
SharePlusWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
SpeechToTextWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SpeechToTextWindows"));
SyncfusionPdfviewerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SyncfusionPdfviewerWindowsPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(

View File

@@ -4,13 +4,18 @@
list(APPEND FLUTTER_PLUGIN_LIST
file_saver
file_selector_windows
firebase_auth
firebase_core
fl_downloader
flutter_tts
geolocator_windows
local_auth_windows
printing
record_windows
screen_brightness_windows
share_plus
speech_to_text_windows
syncfusion_pdfviewer_windows
url_launcher_windows
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB