Compare commits
40 Commits
f137ea41ac
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 971623af77 | |||
| 84cb6b2e83 | |||
| 6e07a55885 | |||
| 8fb31695a8 | |||
| 4fafa35888 | |||
| 0cf9634c5d | |||
| 787a8057b2 | |||
| 5f911d51f9 | |||
| 8da29792b4 | |||
| fd4c34c59d | |||
| 5e003a4d71 | |||
| dca595bf60 | |||
| fcf1bbbb15 | |||
| 8a0c0d7dba | |||
| ff7f363983 | |||
| a54f1c61ae | |||
| 843997e58c | |||
| cbe70e2e44 | |||
| 3778ebb261 | |||
| c911e88453 | |||
| b1487839a7 | |||
| 518dd1300e | |||
| 221030eff3 | |||
| 707b49c088 | |||
| 5135629b33 | |||
| bb64be077f | |||
| 281ea863e8 | |||
| 64af64f28b | |||
| 1c0dd6d328 | |||
| 07d4ba4afa | |||
| 6ad6b6ccbd | |||
| ce2575035f | |||
| baea2c9fdb | |||
| 27639cb964 | |||
| 1143d11054 | |||
| 213f3d418d | |||
| e33a62b909 | |||
| ebab9bae52 | |||
| 82c25c5406 | |||
| 3f0fc08a5c |
@@ -48,13 +48,15 @@ origins = [
|
|||||||
"http://MIH-API-Hub",
|
"http://MIH-API-Hub",
|
||||||
"http://api.mzansi-innovation-hub.co.za",
|
"http://api.mzansi-innovation-hub.co.za",
|
||||||
"http://app.mzansi-innovation-hub.co.za",
|
"http://app.mzansi-innovation-hub.co.za",
|
||||||
|
"https://api.mzansi-innovation-hub.co.za",
|
||||||
|
"https://app.mzansi-innovation-hub.co.za",
|
||||||
]
|
]
|
||||||
|
|
||||||
init(
|
init(
|
||||||
app_info=InputAppInfo(
|
app_info=InputAppInfo(
|
||||||
app_name="Mzansi Innovation Hub",
|
app_name="Mzansi Innovation Hub",
|
||||||
api_domain="http://localhost:8080/",
|
api_domain="http://localhost:8080/",
|
||||||
website_domain="http://app.mzansi-innovation-hub.co.za",
|
website_domain="https://app.mzansi-innovation-hub.co.za",
|
||||||
api_base_path="/auth",
|
api_base_path="/auth",
|
||||||
website_base_path="/auth"
|
website_base_path="/auth"
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ watchfiles
|
|||||||
python-multipart
|
python-multipart
|
||||||
python-dotenv
|
python-dotenv
|
||||||
xlrd
|
xlrd
|
||||||
supertokens-python
|
supertokens-python==0.24.0
|
||||||
sniffio
|
sniffio
|
||||||
@@ -26,7 +26,15 @@ abstract class AppEnviroment {
|
|||||||
baseApiUrl = "http://localhost:8080";
|
baseApiUrl = "http://localhost:8080";
|
||||||
baseFileUrl = "http://localhost:9000";
|
baseFileUrl = "http://localhost:9000";
|
||||||
baseAiUrl = "http://localhost:11434";
|
baseAiUrl = "http://localhost:11434";
|
||||||
bannerAdUnitId = 'ca-app-pub-3940256099942544/2435281174';
|
bannerAdUnitId = 'ca-app-pub-3940256099942544/2435281174'; // IOS ID
|
||||||
|
break;
|
||||||
|
} else if (Platform.isIOS || Platform.isLinux) {
|
||||||
|
//================= Web Dev Urls =================
|
||||||
|
baseAppUrl = "http://localhost:80";
|
||||||
|
baseApiUrl = "http://localhost:8080";
|
||||||
|
baseFileUrl = "http://localhost:9000";
|
||||||
|
baseAiUrl = "http://localhost:11434";
|
||||||
|
bannerAdUnitId = 'ca-app-pub-3940256099942544/2435281174'; // IOS ID
|
||||||
break;
|
break;
|
||||||
} else if (Platform.isAndroid) {
|
} else if (Platform.isAndroid) {
|
||||||
//================= Android Dev Urls =================
|
//================= Android Dev Urls =================
|
||||||
@@ -35,14 +43,6 @@ abstract class AppEnviroment {
|
|||||||
baseFileUrl = "http://10.0.2.2:9000";
|
baseFileUrl = "http://10.0.2.2:9000";
|
||||||
baseAiUrl = "http://10.0.2.2:11434";
|
baseAiUrl = "http://10.0.2.2:11434";
|
||||||
bannerAdUnitId = 'ca-app-pub-3940256099942544/9214589741';
|
bannerAdUnitId = 'ca-app-pub-3940256099942544/9214589741';
|
||||||
} else {
|
|
||||||
//================= Web & iOS Dev Urls =================
|
|
||||||
baseAppUrl = "http://localhost:80";
|
|
||||||
baseApiUrl = "http://localhost:8080";
|
|
||||||
baseFileUrl = "http://localhost:9000";
|
|
||||||
baseAiUrl = "http://localhost:11434";
|
|
||||||
bannerAdUnitId = 'ca-app-pub-3940256099942544/2435281174';
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case Enviroment.prod:
|
case Enviroment.prod:
|
||||||
|
|||||||
@@ -98,6 +98,12 @@ class MihTheme {
|
|||||||
return "Android";
|
return "Android";
|
||||||
} else if (platform == TargetPlatform.iOS) {
|
} else if (platform == TargetPlatform.iOS) {
|
||||||
return "iOS";
|
return "iOS";
|
||||||
|
} else if (platform == TargetPlatform.linux) {
|
||||||
|
return "Linux";
|
||||||
|
} else if (platform == TargetPlatform.macOS) {
|
||||||
|
return "macOS";
|
||||||
|
} else if (platform == TargetPlatform.windows) {
|
||||||
|
return "Windows";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "Other";
|
return "Other";
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:country_code_picker/country_code_picker.dart';
|
import 'package:country_code_picker/country_code_picker.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||||
import 'package:geolocator/geolocator.dart';
|
import 'package:geolocator/geolocator.dart';
|
||||||
@@ -451,6 +454,7 @@ class _PackageToolOneState extends State<PackageToolOne> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS))
|
||||||
MihBannerAd(),
|
MihBannerAd(),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Divider(
|
Divider(
|
||||||
@@ -774,6 +778,7 @@ class _PackageToolOneState extends State<PackageToolOne> {
|
|||||||
MihCircleAvatar(
|
MihCircleAvatar(
|
||||||
imageFile: imagePreview,
|
imageFile: imagePreview,
|
||||||
width: 50,
|
width: 50,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: _fileNameController,
|
fileNameController: _fileNameController,
|
||||||
userSelectedfile: file,
|
userSelectedfile: file,
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ class _MihBusinessProfilePreviewState extends State<MihBusinessProfilePreview> {
|
|||||||
: MihCircleAvatar(
|
: MihCircleAvatar(
|
||||||
imageFile: widget.imageFile,
|
imageFile: widget.imageFile,
|
||||||
width: profilePictureWidth,
|
width: profilePictureWidth,
|
||||||
|
expandable: false,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: TextEditingController(),
|
fileNameController: TextEditingController(),
|
||||||
userSelectedfile: null,
|
userSelectedfile: null,
|
||||||
|
|||||||
@@ -2,13 +2,17 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:ken_logger/ken_logger.dart';
|
||||||
import 'package:mzansi_innovation_hub/main.dart';
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||||
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||||
|
|
||||||
class MihCircleAvatar extends StatefulWidget {
|
class MihCircleAvatar extends StatefulWidget {
|
||||||
final ImageProvider<Object>? imageFile;
|
final ImageProvider<Object>? imageFile;
|
||||||
final double width;
|
final double width;
|
||||||
|
final bool expandable;
|
||||||
final bool editable;
|
final bool editable;
|
||||||
final TextEditingController? fileNameController;
|
final TextEditingController? fileNameController;
|
||||||
final onChange;
|
final onChange;
|
||||||
@@ -19,6 +23,7 @@ class MihCircleAvatar extends StatefulWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.imageFile,
|
required this.imageFile,
|
||||||
required this.width,
|
required this.width,
|
||||||
|
required this.expandable,
|
||||||
required this.editable,
|
required this.editable,
|
||||||
required this.fileNameController,
|
required this.fileNameController,
|
||||||
required this.userSelectedfile,
|
required this.userSelectedfile,
|
||||||
@@ -35,23 +40,33 @@ class _MihCircleAvatarState extends State<MihCircleAvatar> {
|
|||||||
late ImageProvider<Object>? imagePreview;
|
late ImageProvider<Object>? imagePreview;
|
||||||
|
|
||||||
ImageProvider<Object>? getAvatar() {
|
ImageProvider<Object>? getAvatar() {
|
||||||
// Color dark = const Color(0XFF3A4454);
|
|
||||||
if (widget.imageFile == null) {
|
if (widget.imageFile == null) {
|
||||||
return null;
|
return null;
|
||||||
// if (widget.backgroundColor == dark) {
|
|
||||||
// print("here in light icon");
|
|
||||||
// return const AssetImage(
|
|
||||||
// 'lib/mih_package_components/assets/images/i-dont-know-light.png');
|
|
||||||
// } else {
|
|
||||||
// print("here in dark icon");
|
|
||||||
// return const AssetImage(
|
|
||||||
// 'lib/mih_package_components/assets/images/i-dont-know-dark.png');
|
|
||||||
// }
|
|
||||||
} else {
|
} else {
|
||||||
return widget.imageFile;
|
return widget.imageFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void expandAvatar() {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return MihPackageWindow(
|
||||||
|
fullscreen: true,
|
||||||
|
windowTitle: "",
|
||||||
|
scrollbarOn: false,
|
||||||
|
onWindowTapClose: () {
|
||||||
|
context.pop();
|
||||||
|
},
|
||||||
|
windowBody: SizedBox.expand(
|
||||||
|
child: InteractiveViewer(
|
||||||
|
child: Image(image: imagePreview!),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -62,8 +77,14 @@ class _MihCircleAvatarState extends State<MihCircleAvatar> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return GestureDetector(
|
||||||
// color: Colors.white,
|
onTap: widget.expandable
|
||||||
|
? () {
|
||||||
|
KenLogger.success("Avatar tapped");
|
||||||
|
expandAvatar();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
width: widget.width,
|
width: widget.width,
|
||||||
height: widget.width,
|
height: widget.width,
|
||||||
@@ -106,7 +127,8 @@ class _MihCircleAvatarState extends State<MihCircleAvatar> {
|
|||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
backgroundColor: WidgetStateProperty.all<Color>(
|
backgroundColor: WidgetStateProperty.all<Color>(
|
||||||
MihColors.getGreenColor(
|
MihColors.getGreenColor(
|
||||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||||
|
"Dark"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -116,7 +138,9 @@ class _MihCircleAvatarState extends State<MihCircleAvatar> {
|
|||||||
type: FileType.image,
|
type: FileType.image,
|
||||||
);
|
);
|
||||||
// print("Here 1");
|
// print("Here 1");
|
||||||
if (MzansiInnovationHub.of(context)!.theme.getPlatform() ==
|
if (MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.getPlatform() ==
|
||||||
"Web") {
|
"Web") {
|
||||||
// print("Here 2");
|
// print("Here 2");
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
@@ -168,6 +192,7 @@ class _MihCircleAvatarState extends State<MihCircleAvatar> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,18 @@ class _MihDropdownFieldState extends State<MihDropdownField> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Theme(
|
child: Theme(
|
||||||
data: Theme.of(context).copyWith(
|
data: Theme.of(context).copyWith(
|
||||||
|
scrollbarTheme: ScrollbarThemeData(
|
||||||
|
thumbColor: WidgetStatePropertyAll(
|
||||||
|
MihColors.getPrimaryColor(
|
||||||
|
MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.mode ==
|
||||||
|
"Dark")),
|
||||||
|
thickness: const WidgetStatePropertyAll(6),
|
||||||
|
radius: const Radius.circular(10),
|
||||||
|
thumbVisibility: const WidgetStatePropertyAll(
|
||||||
|
true), // Always show when scrolling
|
||||||
|
),
|
||||||
textSelectionTheme: TextSelectionThemeData(
|
textSelectionTheme: TextSelectionThemeData(
|
||||||
cursorColor: MihColors.getPrimaryColor(
|
cursorColor: MihColors.getPrimaryColor(
|
||||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:ken_logger/ken_logger.dart';
|
import 'package:ken_logger/ken_logger.dart';
|
||||||
import 'package:mzansi_innovation_hub/main.dart';
|
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_scack_bar.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_scack_bar.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_packages/mih_home/components/mih_app_drawer.dart';
|
import 'package:mzansi_innovation_hub/mih_packages/mih_home/components/mih_app_drawer.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||||
@@ -100,7 +102,7 @@ class _MihPackageState extends State<MihPackage>
|
|||||||
// _peakAnimation();
|
// _peakAnimation();
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
if (!MzansiInnovationHub.of(context)!.theme.kIsWeb) {
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||||
// Trigger the peak animation only AFTER the route transition is complete
|
// Trigger the peak animation only AFTER the route transition is complete
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
final ModalRoute? currentRoute = ModalRoute.of(context);
|
final ModalRoute? currentRoute = ModalRoute.of(context);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:app_settings/app_settings.dart';
|
import 'package:app_settings/app_settings.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:local_auth/local_auth.dart';
|
import 'package:local_auth/local_auth.dart';
|
||||||
@@ -155,7 +157,8 @@ class _MihPackageTileState extends State<MihPackageTile> {
|
|||||||
Future<void> authenticateUser() async {
|
Future<void> authenticateUser() async {
|
||||||
if (widget.authenticateUser != null &&
|
if (widget.authenticateUser != null &&
|
||||||
widget.authenticateUser! &&
|
widget.authenticateUser! &&
|
||||||
!kIsWeb) {
|
!kIsWeb &&
|
||||||
|
!Platform.isLinux) {
|
||||||
if (await isUserAuthenticated()) {
|
if (await isUserAuthenticated()) {
|
||||||
widget.onTap();
|
widget.onTap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class MihPackageWindow extends StatefulWidget {
|
|||||||
final Color? foregroundColor;
|
final Color? foregroundColor;
|
||||||
final bool? borderOn;
|
final bool? borderOn;
|
||||||
final bool fullscreen;
|
final bool fullscreen;
|
||||||
|
final bool? scrollbarOn;
|
||||||
const MihPackageWindow({
|
const MihPackageWindow({
|
||||||
super.key,
|
super.key,
|
||||||
required this.fullscreen,
|
required this.fullscreen,
|
||||||
@@ -23,6 +24,7 @@ class MihPackageWindow extends StatefulWidget {
|
|||||||
required this.onWindowTapClose,
|
required this.onWindowTapClose,
|
||||||
required this.windowBody,
|
required this.windowBody,
|
||||||
this.borderOn,
|
this.borderOn,
|
||||||
|
this.scrollbarOn,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.foregroundColor,
|
this.foregroundColor,
|
||||||
});
|
});
|
||||||
@@ -177,7 +179,13 @@ class _MihPackageWindowState extends State<MihPackageWindow> {
|
|||||||
getHeader(),
|
getHeader(),
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(child: widget.windowBody)),
|
child: widget.scrollbarOn != null || !widget.scrollbarOn!
|
||||||
|
? widget.windowBody
|
||||||
|
: MihSingleChildScroll(
|
||||||
|
scrollbarOn: true,
|
||||||
|
child: widget.windowBody,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ class _MihPersonalProfilePreviewState extends State<MihPersonalProfilePreview> {
|
|||||||
: MihCircleAvatar(
|
: MihCircleAvatar(
|
||||||
imageFile: widget.imageFile,
|
imageFile: widget.imageFile,
|
||||||
width: profilePictureWidth,
|
width: profilePictureWidth,
|
||||||
|
expandable: false,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: TextEditingController(),
|
fileNameController: TextEditingController(),
|
||||||
userSelectedfile: null,
|
userSelectedfile: null,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mzansi_innovation_hub/main.dart';
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||||
@@ -21,72 +20,30 @@ class _MihAttributesState extends State<MihAttributes> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TableRow displayIcon(IconData icon, String creator, String link) {
|
Widget displayAttribution(IconData resource, String creator, String link) {
|
||||||
return TableRow(
|
return GestureDetector(
|
||||||
children: [
|
onTap: () {
|
||||||
TableCell(
|
|
||||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 150,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 15.0),
|
|
||||||
child: FittedBox(
|
|
||||||
child: Center(
|
|
||||||
child: Icon(
|
|
||||||
icon,
|
|
||||||
// size: 125,
|
|
||||||
color: MihColors.getSecondaryColor(
|
|
||||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TableCell(
|
|
||||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(15.0),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
creator,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TableCell(
|
|
||||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 15.0),
|
|
||||||
child: MihButton(
|
|
||||||
onPressed: () {
|
|
||||||
launchUrlLink(
|
launchUrlLink(
|
||||||
Uri.parse(
|
Uri.parse(
|
||||||
link,
|
link,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
buttonColor: MihColors.getGreenColor(
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
resource,
|
||||||
|
color: MihColors.getSecondaryColor(
|
||||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||||
width: 100,
|
size: 100,
|
||||||
child: Text(
|
|
||||||
"Visit",
|
|
||||||
style: TextStyle(
|
|
||||||
color: MihColors.getPrimaryColor(
|
|
||||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
Text(
|
||||||
|
creator,
|
||||||
|
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,157 +89,50 @@ class _MihAttributesState extends State<MihAttributes> {
|
|||||||
height: 10,
|
height: 10,
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 700,
|
width: 900,
|
||||||
child: Table(
|
child: Wrap(
|
||||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
alignment: WrapAlignment.center,
|
||||||
columnWidths: const {
|
runSpacing: 10,
|
||||||
0: FlexColumnWidth(1),
|
spacing: 10,
|
||||||
1: FlexColumnWidth(1),
|
|
||||||
2: FlexColumnWidth(1),
|
|
||||||
},
|
|
||||||
children: [
|
children: [
|
||||||
const TableRow(
|
displayAttribution(MihIcons.mihRing, "Tarah Meth",
|
||||||
children: [
|
|
||||||
TableCell(
|
|
||||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 15.0),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
"Resources",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 25,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TableCell(
|
|
||||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 15.0),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
"Creator",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 25,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TableCell(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 15.0),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
"Link",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 25,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
displayIcon(MihIcons.mihRing, "Tarah Meth",
|
|
||||||
"https://www.linkedin.com/in/tarah-meth-3b6309254/"),
|
"https://www.linkedin.com/in/tarah-meth-3b6309254/"),
|
||||||
displayIcon(MihIcons.mihLogo, "Tarah Meth",
|
displayAttribution(MihIcons.mihLogo, "Tarah Meth",
|
||||||
"https://www.linkedin.com/in/tarah-meth-3b6309254/"),
|
"https://www.linkedin.com/in/tarah-meth-3b6309254/"),
|
||||||
displayIcon(
|
displayAttribution(
|
||||||
MihIcons.mzansiAi, "Ollama", "https://ollama.com/"),
|
MihIcons.mzansiAi, "Ollama", "https://ollama.com/"),
|
||||||
displayIcon(MihIcons.mzansiWallet, "Freepik",
|
displayAttribution(MihIcons.mzansiWallet, "Freepik",
|
||||||
"https://www.flaticon.com/free-icon/wallet-passes-app_3884407?term=wallet&page=1&position=21&origin=search&related_id=3884407"),
|
"https://www.flaticon.com/free-icon/wallet-passes-app_3884407?term=wallet&page=1&position=21&origin=search&related_id=3884407"),
|
||||||
displayIcon(MihIcons.patientProfile, "RaftelDesign",
|
displayAttribution(MihIcons.patientProfile, "RaftelDesign",
|
||||||
"https://www.flaticon.com/free-icon/patient_2376100?term=medication&page=1&position=6&origin=search&related_id=2376100"),
|
"https://www.flaticon.com/free-icon/patient_2376100?term=medication&page=1&position=6&origin=search&related_id=2376100"),
|
||||||
displayIcon(MihIcons.patientProfile, "Srip",
|
displayAttribution(MihIcons.patientProfile, "Srip",
|
||||||
"https://www.flaticon.com/free-icon/hospital_1233930?term=medical+snake&page=1&position=7&origin=search&related_id=1233930"),
|
"https://www.flaticon.com/free-icon/hospital_1233930?term=medical+snake&page=1&position=7&origin=search&related_id=1233930"),
|
||||||
displayIcon(MihIcons.calendar, "Freepik",
|
displayAttribution(MihIcons.calendar, "Freepik",
|
||||||
"https://www.flaticon.com/free-icon/calendar_2278049?term=calendar&page=1&position=5&origin=search&related_id=2278049"),
|
"https://www.flaticon.com/free-icon/calendar_2278049?term=calendar&page=1&position=5&origin=search&related_id=2278049"),
|
||||||
displayIcon(MihIcons.calculator, "Freepik",
|
displayAttribution(MihIcons.calculator, "Freepik",
|
||||||
"https://www.flaticon.com/free-icon/calculator_2374409?term=calculator&page=1&position=20&origin=search&related_id=2374409"),
|
"https://www.flaticon.com/free-icon/calculator_2374409?term=calculator&page=1&position=20&origin=search&related_id=2374409"),
|
||||||
displayIcon(MihIcons.aboutMih, "Chanut",
|
displayAttribution(MihIcons.aboutMih, "Chanut",
|
||||||
"https://www.flaticon.com/free-icon/info_151776?term=about&page=1&position=8&origin=search&related_id=151776"),
|
"https://www.flaticon.com/free-icon/info_151776?term=about&page=1&position=8&origin=search&related_id=151776"),
|
||||||
displayIcon(MihIcons.personalProfile, "Freepik",
|
displayAttribution(MihIcons.personalProfile, "Freepik",
|
||||||
"https://www.flaticon.com/free-icon/user_1077063?term=profile&page=1&position=6&origin=search&related_id=1077063"),
|
"https://www.flaticon.com/free-icon/user_1077063?term=profile&page=1&position=6&origin=search&related_id=1077063"),
|
||||||
displayIcon(MihIcons.businessProfile, "Gravisio",
|
displayAttribution(MihIcons.businessProfile, "Gravisio",
|
||||||
"https://www.flaticon.com/free-icon/contractor_11813336?term=company+profile&page=1&position=2&origin=search&related_id=11813336"),
|
"https://www.flaticon.com/free-icon/contractor_11813336?term=company+profile&page=1&position=2&origin=search&related_id=11813336"),
|
||||||
displayIcon(MihIcons.patientManager, "Vector Tank",
|
displayAttribution(MihIcons.patientManager, "Vector Tank",
|
||||||
"https://www.flaticon.com/free-icon/doctor_10215061?term=doctor&page=1&position=73&origin=search&related_id=10215061"),
|
"https://www.flaticon.com/free-icon/doctor_10215061?term=doctor&page=1&position=73&origin=search&related_id=10215061"),
|
||||||
displayIcon(MihIcons.profileSetup, "Freepik",
|
displayAttribution(MihIcons.profileSetup, "Freepik",
|
||||||
"https://www.flaticon.com/free-icon/add-user_748137?term=profile+add&page=1&position=1&origin=search&related_id=748137"),
|
"https://www.flaticon.com/free-icon/add-user_748137?term=profile+add&page=1&position=1&origin=search&related_id=748137"),
|
||||||
displayIcon(MihIcons.businessSetup, "kerismaker",
|
displayAttribution(MihIcons.businessSetup, "kerismaker",
|
||||||
"https://www.flaticon.com/free-icon/business_13569850?term=company+add&page=1&position=25&origin=search&related_id=13569850"),
|
"https://www.flaticon.com/free-icon/business_13569850?term=company+add&page=1&position=25&origin=search&related_id=13569850"),
|
||||||
displayIcon(MihIcons.calculator, "fawazahmed0",
|
displayAttribution(MihIcons.calculator, "fawazahmed0",
|
||||||
"https://github.com/fawazahmed0/exchange-api"),
|
"https://github.com/fawazahmed0/exchange-api"),
|
||||||
displayIcon(MihIcons.iDontKnow, "Freepik",
|
displayAttribution(MihIcons.iDontKnow, "Freepik",
|
||||||
"https://www.flaticon.com/free-icon/i-dont-know_5359909?term=i+dont+know&page=1&position=7&origin=search&related_id=5359909"),
|
"https://www.flaticon.com/free-icon/i-dont-know_5359909?term=i+dont+know&page=1&position=7&origin=search&related_id=5359909"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// SizedBox(
|
const SizedBox(
|
||||||
// width: 500,
|
height: 30,
|
||||||
// child: Column(
|
),
|
||||||
// children: [
|
|
||||||
// const SizedBox(
|
|
||||||
// width: double.infinity,
|
|
||||||
// child: Row(
|
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
// mainAxisSize: MainAxisSize.max,
|
|
||||||
// children: [
|
|
||||||
// Flexible(
|
|
||||||
// child: Text(
|
|
||||||
// "Icon",
|
|
||||||
// style: TextStyle(
|
|
||||||
// fontSize: 25,
|
|
||||||
// fontWeight: FontWeight.bold,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// Flexible(
|
|
||||||
// child: Text(
|
|
||||||
// "Creator",
|
|
||||||
// style: TextStyle(
|
|
||||||
// fontSize: 25,
|
|
||||||
// fontWeight: FontWeight.bold,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// Flexible(
|
|
||||||
// child: Text(
|
|
||||||
// "Link",
|
|
||||||
// style: TextStyle(
|
|
||||||
// fontSize: 25,
|
|
||||||
// fontWeight: FontWeight.bold,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// const Padding(
|
|
||||||
// padding: EdgeInsets.symmetric(vertical: 10.0),
|
|
||||||
// child: Divider(),
|
|
||||||
// ),
|
|
||||||
// displayIcon(MihIcons.mihLogo, "Tarah Meth",
|
|
||||||
// "https://app.mzansi-innovation-hub.co.za/"),
|
|
||||||
// const SizedBox(height: 10),
|
|
||||||
// displayIcon(MihIcons.mihLogo, "Test",
|
|
||||||
// "https://www.flaticon.com/free-icons/mih"),
|
|
||||||
// const SizedBox(height: 10),
|
|
||||||
// displayIcon(MihIcons.mihLogo, "Test",
|
|
||||||
// "https://www.flaticon.com/free-icons/mih"),
|
|
||||||
// const SizedBox(height: 10),
|
|
||||||
// displayIcon(MihIcons.mihLogo, "Test",
|
|
||||||
// "https://www.flaticon.com/free-icons/mih"),
|
|
||||||
// const SizedBox(height: 10),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:mzansi_innovation_hub/main.dart';
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
@@ -157,7 +160,11 @@ class _CurrencyExchangeRateState extends State<CurrencyExchangeRate> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Consumer(builder: (context, bannerAdDisplay, child) {
|
Consumer(builder: (context, bannerAdDisplay, child) {
|
||||||
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||||
return MihBannerAd();
|
return MihBannerAd();
|
||||||
|
} else {
|
||||||
|
return const SizedBox(height: 0);
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:mzansi_innovation_hub/main.dart';
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_banner_ad.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_banner_ad.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||||
@@ -229,7 +232,11 @@ class _TipCalcState extends State<TipCalc> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Consumer(builder: (context, bannerAdDisplay, child) {
|
Consumer(builder: (context, bannerAdDisplay, child) {
|
||||||
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||||
return MihBannerAd();
|
return MihBannerAd();
|
||||||
|
} else {
|
||||||
|
return const SizedBox(height: 0);
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
// if (splitBillController.text == "Yes") const Divider(),
|
// if (splitBillController.text == "Yes") const Divider(),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
|
|||||||
? mzansiProfileProvider.userProfilePicture
|
? mzansiProfileProvider.userProfilePicture
|
||||||
: mzansiProfileProvider.businessProfilePicture,
|
: mzansiProfileProvider.businessProfilePicture,
|
||||||
width: 60,
|
width: 60,
|
||||||
|
expandable: false,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: proPicController,
|
fileNameController: proPicController,
|
||||||
onChange: (_) {},
|
onChange: (_) {},
|
||||||
|
|||||||
@@ -353,6 +353,7 @@ class _MihHomeState extends State<MihHome> {
|
|||||||
key: Key(imageKey),
|
key: Key(imageKey),
|
||||||
imageFile: currentImage,
|
imageFile: currentImage,
|
||||||
width: 50,
|
width: 50,
|
||||||
|
expandable: false,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: null,
|
fileNameController: null,
|
||||||
userSelectedfile: null,
|
userSelectedfile: null,
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ class _BuildMinesweeperLeaderboardListState
|
|||||||
key: UniqueKey(),
|
key: UniqueKey(),
|
||||||
imageFile: imageFile,
|
imageFile: imageFile,
|
||||||
width: 80,
|
width: 80,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: null,
|
fileNameController: null,
|
||||||
userSelectedfile: null,
|
userSelectedfile: null,
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ class LeaderboardUserRanking extends StatelessWidget {
|
|||||||
.toString()), // Use ValueKey for stable identity
|
.toString()), // Use ValueKey for stable identity
|
||||||
imageFile: asyncSnapshot.data,
|
imageFile: asyncSnapshot.data,
|
||||||
width: 60,
|
width: 60,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: null,
|
fileNameController: null,
|
||||||
userSelectedfile: null,
|
userSelectedfile: null,
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
@@ -851,7 +853,9 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
_timer != null ? MihBannerAd() : SizedBox(),
|
_timer != null && !kIsWeb && (Platform.isAndroid || Platform.isIOS)
|
||||||
|
? MihBannerAd()
|
||||||
|
: SizedBox(),
|
||||||
SizedBox(height: 15),
|
SizedBox(height: 15),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ class _MihMineSweeperLeaderBoardState extends State<MyScoreBoard> {
|
|||||||
child: MihCircleAvatar(
|
child: MihCircleAvatar(
|
||||||
imageFile: profileProvider.userProfilePicture,
|
imageFile: profileProvider.userProfilePicture,
|
||||||
width: 150,
|
width: 150,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: null,
|
fileNameController: null,
|
||||||
userSelectedfile: null,
|
userSelectedfile: null,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -112,16 +113,36 @@ class _MihAiChatState extends State<MihAiChat> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
void speakLastMessage(MzansiAiProvider aiProvider) {
|
void speakLastMessage(MzansiAiProvider aiProvider) {
|
||||||
final history = aiProvider.ollamaProvider.history;
|
final history = aiProvider.ollamaProvider.history;
|
||||||
if (history.isNotEmpty) {
|
if (history.isEmpty) return;
|
||||||
|
|
||||||
final historyList = history.toList();
|
final historyList = history.toList();
|
||||||
|
String? textToSpeak;
|
||||||
|
|
||||||
|
// Find the last LLM message
|
||||||
for (int i = historyList.length - 1; i >= 0; i--) {
|
for (int i = historyList.length - 1; i >= 0; i--) {
|
||||||
if (historyList[i].origin == MessageOrigin.llm &&
|
if (historyList[i].origin == MessageOrigin.llm &&
|
||||||
historyList[i].text != null &&
|
historyList[i].text != null &&
|
||||||
historyList[i].text!.isNotEmpty) {
|
historyList[i].text!.isNotEmpty) {
|
||||||
_flutterTts.speak(historyList[i].text!);
|
textToSpeak = historyList[i].text!;
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (textToSpeak != null) {
|
||||||
|
if (!kIsWeb && Platform.isLinux) {
|
||||||
|
// Linux Workaround: Use Speech Dispatcher (standard on most distros)
|
||||||
|
// '-t female1' is optional for voice variety
|
||||||
|
Process.run('spd-say', [textToSpeak]);
|
||||||
|
|
||||||
|
// Since spd-say doesn't have an easy "completion handler" via CLI,
|
||||||
|
// we manually toggle the UI state or just leave it off.
|
||||||
|
aiProvider.setTTSstate(true);
|
||||||
|
Future.delayed(
|
||||||
|
Duration(seconds: 5), () => aiProvider.setTTSstate(false));
|
||||||
|
} else {
|
||||||
|
// Your existing mobile/web logic
|
||||||
|
_flutterTts.speak(textToSpeak);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,11 +204,16 @@ class _MihAiChatState extends State<MihAiChat> with WidgetsBindingObserver {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
void stopTTS(MzansiAiProvider aiProvider) {
|
void stopTTS(MzansiAiProvider aiProvider) {
|
||||||
|
if (!kIsWeb && Platform.isLinux) {
|
||||||
|
Process.run('spd-say', ['-S']); // The -S flag stops current speech
|
||||||
|
} else {
|
||||||
_flutterTts.stop();
|
_flutterTts.stop();
|
||||||
|
}
|
||||||
aiProvider.setTTSstate(false);
|
aiProvider.setTTSstate(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initTts(MzansiAiProvider aiProvider) async {
|
Future<void> initTts(MzansiAiProvider aiProvider) async {
|
||||||
|
if (!kIsWeb && Platform.isLinux) return;
|
||||||
try {
|
try {
|
||||||
await _flutterTts.setSpeechRate(!kIsWeb ? 0.55 : 1);
|
await _flutterTts.setSpeechRate(!kIsWeb ? 0.55 : 1);
|
||||||
// await _flutterTts.setLanguage("en-US");
|
// await _flutterTts.setLanguage("en-US");
|
||||||
@@ -258,7 +284,9 @@ class _MihAiChatState extends State<MihAiChat> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
if (!kIsWeb && !Platform.isLinux) {
|
||||||
_flutterTts.stop();
|
_flutterTts.stop();
|
||||||
|
}
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,6 +271,7 @@ class _MihUpdateBusinessDetailsWindowState
|
|||||||
: mzansiProfileProvider
|
: mzansiProfileProvider
|
||||||
.businessProfilePicture,
|
.businessProfilePicture,
|
||||||
width: 150,
|
width: 150,
|
||||||
|
expandable: false,
|
||||||
editable: true,
|
editable: true,
|
||||||
fileNameController: fileNameController,
|
fileNameController: fileNameController,
|
||||||
userSelectedfile: newSelectedLogoPic,
|
userSelectedfile: newSelectedLogoPic,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import 'package:mzansi_innovation_hub/main.dart';
|
|||||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
|
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_image_display.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_image_display.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||||
@@ -133,27 +132,29 @@ class _MihUpdateMyBusinessUserDetailsState
|
|||||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||||
? EdgeInsets.symmetric(horizontal: width * 0.2)
|
? EdgeInsets.symmetric(horizontal: width * 0.2)
|
||||||
: EdgeInsets.symmetric(horizontal: width * 0.075),
|
: EdgeInsets.symmetric(horizontal: width * 0.075),
|
||||||
child: Column(
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
children: [
|
children: [
|
||||||
MihForm(
|
MihForm(
|
||||||
formKey: _formKey,
|
formKey: _formKey,
|
||||||
formFields: [
|
formFields: [
|
||||||
Center(
|
// Center(
|
||||||
child: MihCircleAvatar(
|
// child: MihCircleAvatar(
|
||||||
imageFile: mzansiProfileProvider.userProfilePicture,
|
// imageFile: mzansiProfileProvider.userProfilePicture,
|
||||||
width: 150,
|
// width: 150,
|
||||||
editable: false,
|
// editable: false,
|
||||||
fileNameController: fileNameController,
|
// fileNameController: fileNameController,
|
||||||
userSelectedfile: userPicFile,
|
// userSelectedfile: userPicFile,
|
||||||
frameColor: MihColors.getSecondaryColor(
|
// frameColor: MihColors.getSecondaryColor(
|
||||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
// MzansiInnovationHub.of(context)!.theme.mode ==
|
||||||
"Dark"),
|
// "Dark"),
|
||||||
backgroundColor: MihColors.getPrimaryColor(
|
// backgroundColor: MihColors.getPrimaryColor(
|
||||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
// MzansiInnovationHub.of(context)!.theme.mode ==
|
||||||
"Dark"),
|
// "Dark"),
|
||||||
onChange: (_) {},
|
// onChange: (_) {},
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Visibility(
|
Visibility(
|
||||||
visible: false,
|
visible: false,
|
||||||
child: MihTextFormField(
|
child: MihTextFormField(
|
||||||
@@ -302,7 +303,9 @@ class _MihUpdateMyBusinessUserDetailsState
|
|||||||
"Update",
|
"Update",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: MihColors.getPrimaryColor(
|
color: MihColors.getPrimaryColor(
|
||||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.mode ==
|
||||||
"Dark"),
|
"Dark"),
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
@@ -315,6 +318,35 @@ class _MihUpdateMyBusinessUserDetailsState
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Positioned(
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
child: MihButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
submitForm(mzansiProfileProvider);
|
||||||
|
} else {
|
||||||
|
MihAlertServices().inputErrorAlert(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buttonColor: MihColors.getGreenColor(
|
||||||
|
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||||
|
width: 100,
|
||||||
|
height: 25,
|
||||||
|
child: Text(
|
||||||
|
"Update",
|
||||||
|
style: TextStyle(
|
||||||
|
color: MihColors.getPrimaryColor(
|
||||||
|
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||||
|
"Dark"),
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ class _MihBusinessDetailsState extends State<MihBusinessDetails> {
|
|||||||
imageFile:
|
imageFile:
|
||||||
mzansiProfileProvider.businessProfilePicture,
|
mzansiProfileProvider.businessProfilePicture,
|
||||||
width: 150,
|
width: 150,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: fileNameController,
|
fileNameController: fileNameController,
|
||||||
userSelectedfile: newSelectedLogoPic,
|
userSelectedfile: newSelectedLogoPic,
|
||||||
|
|||||||
@@ -330,6 +330,7 @@ class _MihBusinessDetailsSetUpState extends State<MihBusinessDetailsSetUp> {
|
|||||||
? MemoryImage(newSelectedLogoPic!.bytes!)
|
? MemoryImage(newSelectedLogoPic!.bytes!)
|
||||||
: mzansiProfileProvider.businessProfilePicture,
|
: mzansiProfileProvider.businessProfilePicture,
|
||||||
width: 150,
|
width: 150,
|
||||||
|
expandable: false,
|
||||||
editable: true,
|
editable: true,
|
||||||
fileNameController: logoFileNameController,
|
fileNameController: logoFileNameController,
|
||||||
userSelectedfile: newSelectedLogoPic,
|
userSelectedfile: newSelectedLogoPic,
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ class _MihBusinessDetailsViewState extends State<MihBusinessDetailsView> {
|
|||||||
imageFile: CachedNetworkImageProvider(
|
imageFile: CachedNetworkImageProvider(
|
||||||
asyncSnapshot.requireData),
|
asyncSnapshot.requireData),
|
||||||
width: profilePictureWidth,
|
width: profilePictureWidth,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: TextEditingController(),
|
fileNameController: TextEditingController(),
|
||||||
userSelectedfile: file,
|
userSelectedfile: file,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:file_saver/file_saver.dart';
|
import 'package:file_saver/file_saver.dart';
|
||||||
@@ -82,6 +84,19 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
|
|||||||
fileExtension: "png",
|
fileExtension: "png",
|
||||||
mimeType: MimeType.png,
|
mimeType: MimeType.png,
|
||||||
);
|
);
|
||||||
|
} else if (defaultTargetPlatform == TargetPlatform.linux ||
|
||||||
|
defaultTargetPlatform == TargetPlatform.windows) {
|
||||||
|
// Use File Picker to get a save path on Desktop
|
||||||
|
String? outputFile = await FilePicker.platform.saveFile(
|
||||||
|
dialogTitle: 'Please select where to save your QR Code:',
|
||||||
|
fileName: filename,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (outputFile != null) {
|
||||||
|
final file = File(outputFile);
|
||||||
|
await file.writeAsBytes(imageBytes);
|
||||||
|
KenLogger.success("Saved to $outputFile");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
await FileSaver.instance.saveAs(
|
await FileSaver.instance.saveAs(
|
||||||
name: filename,
|
name: filename,
|
||||||
@@ -95,14 +110,14 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
|
|||||||
Future<void> downloadQrCode() async {
|
Future<void> downloadQrCode() async {
|
||||||
if (_isUserSignedIn) {
|
if (_isUserSignedIn) {
|
||||||
await screenshotController.capture().then((image) {
|
await screenshotController.capture().then((image) {
|
||||||
KenLogger.success("Image Captured: $image");
|
// KenLogger.success("Image Captured: $image");
|
||||||
setState(() {
|
setState(() {
|
||||||
businessQRImageFile = image;
|
businessQRImageFile = image;
|
||||||
});
|
});
|
||||||
}).catchError((onError) {
|
}).catchError((onError) {
|
||||||
KenLogger.error(onError);
|
KenLogger.error(onError);
|
||||||
});
|
});
|
||||||
KenLogger.success("QR Code Image Captured : $businessQRImageFile");
|
// KenLogger.success("QR Code Image Captured : $businessQRImageFile");
|
||||||
saveImage(businessQRImageFile!);
|
saveImage(businessQRImageFile!);
|
||||||
} else {
|
} else {
|
||||||
showSignInRequiredAlert();
|
showSignInRequiredAlert();
|
||||||
@@ -211,6 +226,7 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
|
|||||||
imageFile: CachedNetworkImageProvider(
|
imageFile: CachedNetworkImageProvider(
|
||||||
asyncSnapshot.requireData),
|
asyncSnapshot.requireData),
|
||||||
width: profilePictureWidth,
|
width: profilePictureWidth,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: TextEditingController(),
|
fileNameController: TextEditingController(),
|
||||||
userSelectedfile: file,
|
userSelectedfile: file,
|
||||||
|
|||||||
@@ -184,9 +184,12 @@ class _MihMyBusinessUserState extends State<MihMyBusinessUser> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Center(
|
Center(
|
||||||
child: MihCircleAvatar(
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
MihCircleAvatar(
|
||||||
imageFile: mzansiProfileProvider.userProfilePicture,
|
imageFile: mzansiProfileProvider.userProfilePicture,
|
||||||
width: 150,
|
width: 150,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: fileNameController,
|
fileNameController: fileNameController,
|
||||||
userSelectedfile: userPicFile,
|
userSelectedfile: userPicFile,
|
||||||
@@ -198,6 +201,31 @@ class _MihMyBusinessUserState extends State<MihMyBusinessUser> {
|
|||||||
"Dark"),
|
"Dark"),
|
||||||
onChange: (_) {},
|
onChange: (_) {},
|
||||||
),
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 5,
|
||||||
|
right: 5,
|
||||||
|
child: MihButton(
|
||||||
|
onPressed: () {
|
||||||
|
editBizUserProfileWindow(
|
||||||
|
mzansiProfileProvider, width);
|
||||||
|
},
|
||||||
|
buttonColor: MihColors.getGreenColor(
|
||||||
|
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||||
|
"Dark"),
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
child: Icon(
|
||||||
|
Icons.edit,
|
||||||
|
color: MihColors.getPrimaryColor(
|
||||||
|
MzansiInnovationHub.of(context)!
|
||||||
|
.theme
|
||||||
|
.mode ==
|
||||||
|
"Dark"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
buildEmployeeInfoCard(mzansiProfileProvider),
|
buildEmployeeInfoCard(mzansiProfileProvider),
|
||||||
@@ -246,28 +274,6 @@ class _MihMyBusinessUserState extends State<MihMyBusinessUser> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Center(
|
|
||||||
child: MihButton(
|
|
||||||
onPressed: () {
|
|
||||||
editBizUserProfileWindow(
|
|
||||||
mzansiProfileProvider, width);
|
|
||||||
},
|
|
||||||
buttonColor: MihColors.getGreenColor(
|
|
||||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
|
||||||
"Dark"),
|
|
||||||
width: 300,
|
|
||||||
child: Text(
|
|
||||||
"Edit Profile",
|
|
||||||
style: TextStyle(
|
|
||||||
color: MihColors.getPrimaryColor(
|
|
||||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
|
||||||
"Dark"),
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -343,6 +343,7 @@ class _MihEditPersonalProfileWindowState
|
|||||||
? MemoryImage(newSelectedProPic!.bytes!)
|
? MemoryImage(newSelectedProPic!.bytes!)
|
||||||
: mzansiProfileProvider.userProfilePicture,
|
: mzansiProfileProvider.userProfilePicture,
|
||||||
width: 150,
|
width: 150,
|
||||||
|
expandable: false,
|
||||||
editable: true,
|
editable: true,
|
||||||
fileNameController: proPicController,
|
fileNameController: proPicController,
|
||||||
userSelectedfile: newSelectedProPic,
|
userSelectedfile: newSelectedProPic,
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ class _MihPersonalProfileState extends State<MihPersonalProfile> {
|
|||||||
MihCircleAvatar(
|
MihCircleAvatar(
|
||||||
imageFile: mzansiProfileProvider.userProfilePicture,
|
imageFile: mzansiProfileProvider.userProfilePicture,
|
||||||
width: 150,
|
width: 150,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: proPicController,
|
fileNameController: proPicController,
|
||||||
userSelectedfile: newSelectedProPic,
|
userSelectedfile: newSelectedProPic,
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class _MihPersonalProfileViewState extends State<MihPersonalProfileView> {
|
|||||||
imageFile: CachedNetworkImageProvider(
|
imageFile: CachedNetworkImageProvider(
|
||||||
asyncSnapshot.requireData),
|
asyncSnapshot.requireData),
|
||||||
width: profilePictureWidth,
|
width: profilePictureWidth,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: TextEditingController(),
|
fileNameController: TextEditingController(),
|
||||||
userSelectedfile: file,
|
userSelectedfile: file,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@@ -545,7 +547,7 @@ class _BuildLoyaltyCardListState extends State<BuildLoyaltyCardList> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
MihBannerAd()
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) MihBannerAd()
|
||||||
// MihBannerAd(),
|
// MihBannerAd(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -572,7 +574,7 @@ class _BuildLoyaltyCardListState extends State<BuildLoyaltyCardList> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setScreenBrightness(double newBrightness) async {
|
Future<void> setScreenBrightness(double newBrightness) async {
|
||||||
if (!kIsWeb) {
|
if (!kIsWeb && !Platform.isLinux) {
|
||||||
bool canChange =
|
bool canChange =
|
||||||
await ScreenBrightness.instance.canChangeSystemBrightness;
|
await ScreenBrightness.instance.canChangeSystemBrightness;
|
||||||
|
|
||||||
|
|||||||
@@ -314,6 +314,7 @@ class _PatientInfoState extends State<PatientInfo> {
|
|||||||
imageFile:
|
imageFile:
|
||||||
patientManagerProvider.selectedPatientProfilePicture,
|
patientManagerProvider.selectedPatientProfilePicture,
|
||||||
width: 160,
|
width: 160,
|
||||||
|
expandable: true,
|
||||||
editable: false,
|
editable: false,
|
||||||
fileNameController: null,
|
fileNameController: null,
|
||||||
userSelectedfile: null,
|
userSelectedfile: null,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||||
@@ -28,6 +30,7 @@ class MihBannerAdProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loadBannerAd() {
|
void loadBannerAd() {
|
||||||
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||||
if (bannerAd != null) {
|
if (bannerAd != null) {
|
||||||
bannerAd!.dispose();
|
bannerAd!.dispose();
|
||||||
bannerAd = null;
|
bannerAd = null;
|
||||||
@@ -59,4 +62,5 @@ class MihBannerAdProvider extends ChangeNotifier {
|
|||||||
);
|
);
|
||||||
bannerAd!.load();
|
bannerAd!.load();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:mzansi_innovation_hub/main.dart';
|
import 'package:mzansi_innovation_hub/main.dart';
|
||||||
@@ -134,7 +137,9 @@ class MihAlertServices {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
Text(
|
Text(
|
||||||
"To get the most out of MIH, we need your location. Please go to the site settings of the app and enable location services. Once you do that, we can start showing you relevant information based on your location.",
|
!kIsWeb && Platform.isLinux
|
||||||
|
? "To get the most out of MIH, we need your location. Please go to your System Settings and enable location services. Once you do that, we can start showing you relevant information based on your location."
|
||||||
|
: "To get the most out of MIH, we need your location. Please go to the site settings of the app and enable location services. Once you do that, we can start showing you relevant information based on your location.",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: MihColors.getSecondaryColor(
|
color: MihColors.getSecondaryColor(
|
||||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:ken_logger/ken_logger.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -51,6 +54,15 @@ class MihFileApi {
|
|||||||
} finally {
|
} finally {
|
||||||
// Navigator.of(context).pop(); // Always pop loading dialog
|
// Navigator.of(context).pop(); // Always pop loading dialog
|
||||||
}
|
}
|
||||||
|
KenLogger.success("File URL: $fileUrl");
|
||||||
|
if (AppEnviroment.getEnv() == "Dev" && kIsWeb) {
|
||||||
|
fileUrl = fileUrl.replaceAll("10.0.2.2", "127.0.0.1");
|
||||||
|
} else if (AppEnviroment.getEnv() == "Dev" && Platform.isIOS) {
|
||||||
|
fileUrl = fileUrl.replaceAll("10.0.2.2", "127.0.0.1");
|
||||||
|
} else if (AppEnviroment.getEnv() == "Dev" && Platform.isLinux) {
|
||||||
|
fileUrl = fileUrl.replaceAll("10.0.2.2", "127.0.0.1");
|
||||||
|
}
|
||||||
|
KenLogger.success("File URL: $fileUrl");
|
||||||
return fileUrl;
|
return fileUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:geolocator/geolocator.dart';
|
import 'package:geolocator/geolocator.dart';
|
||||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||||
@@ -13,6 +16,12 @@ class MIHLocationAPI {
|
|||||||
///if user has blocked permission (denied or denied forver), user will get error pop up.
|
///if user has blocked permission (denied or denied forver), user will get error pop up.
|
||||||
///if user has granted permission (while in use), function will return Position object.
|
///if user has granted permission (while in use), function will return Position object.
|
||||||
Future<Position?> getGPSPosition(BuildContext context) async {
|
Future<Position?> getGPSPosition(BuildContext context) async {
|
||||||
|
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||||
|
if (!serviceEnabled && !kIsWeb && Platform.isLinux) {
|
||||||
|
// Direct the user to their System Settings
|
||||||
|
MihAlertServices().locationPermissionAlert(context);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
print("Before checkPermission"); // Debug
|
print("Before checkPermission"); // Debug
|
||||||
LocationPermission permission = await Geolocator.checkPermission();
|
LocationPermission permission = await Geolocator.checkPermission();
|
||||||
print("After checkPermission: $permission"); // Debug
|
print("After checkPermission: $permission"); // Debug
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ project(runner LANGUAGES CXX)
|
|||||||
|
|
||||||
# The name of the executable created for the application. Change this to change
|
# The name of the executable created for the application. Change this to change
|
||||||
# the on-disk name of your application.
|
# the on-disk name of your application.
|
||||||
set(BINARY_NAME "patient_manager")
|
set(BINARY_NAME "mzansi_innovation_hub")
|
||||||
# The unique GTK application identifier for this application. See:
|
# The unique GTK application identifier for this application. See:
|
||||||
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||||
set(APPLICATION_ID "com.example.patient_manager")
|
set(APPLICATION_ID "za.co.mzansiinnovationhub.mih")
|
||||||
|
|
||||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||||
# versions of CMake.
|
# versions of CMake.
|
||||||
|
|||||||
BIN
mih_ui/mih_app_flatpak/main.png
Normal file
BIN
mih_ui/mih_app_flatpak/main.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 169 KiB |
12
mih_ui/mih_app_flatpak/za.co.mzansiinnovationhub.mih.desktop
Normal file
12
mih_ui/mih_app_flatpak/za.co.mzansiinnovationhub.mih.desktop
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Type=Application
|
||||||
|
Name=MIH
|
||||||
|
GenericName=Mzansi Innovation Hub
|
||||||
|
Comment=Mzansi Innovation Hub official application
|
||||||
|
Exec=mzansi_innovation_hub
|
||||||
|
Icon=za.co.mzansiinnovationhub.mih
|
||||||
|
Terminal=false
|
||||||
|
Categories=Utility;
|
||||||
|
Keywords=MIH;Mzansi;Innovation;Hub;
|
||||||
|
StartupWMClass=mzansi_innovation_hub
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<component type="desktop-application">
|
||||||
|
|
||||||
|
<id>za.co.mzansiinnovationhub.mih</id>
|
||||||
|
|
||||||
|
<name>MIH</name>
|
||||||
|
<summary>Innovation tools and services for the Mzansi ecosystem</summary>
|
||||||
|
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>GPL-3.0</project_license>
|
||||||
|
<developer_name>Mzansi Innovation Hub</developer_name>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
MIH (Mzansi Innovation Hub) is a modern desktop application designed to provide
|
||||||
|
innovation tools and services for users. Built with Flutter, it offers a
|
||||||
|
high-performance, responsive interface tailored for the Linux desktop.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Access professional innovation resources</li>
|
||||||
|
<li>Streamlined user interface for efficiency</li>
|
||||||
|
<li>Native integration with Linux desktop environments</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<launchable type="desktop-id">za.co.mzansiinnovationhub.mih.desktop</launchable>
|
||||||
|
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default">
|
||||||
|
<caption>The main dashboard of the MIH application.</caption>
|
||||||
|
<image>https://git.mzansi-innovation-hub.co.za/yaso_meth/mih-project/raw/main/screenshots/main.png</image>
|
||||||
|
</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
|
||||||
|
<url type="homepage">https://mzansi-innovation-hub.co.za/</url>
|
||||||
|
<url type="bugtracker">https://git.mzansi-innovation-hub.co.za/yaso_meth/mih-project/issues</url>
|
||||||
|
|
||||||
|
<provides>
|
||||||
|
<binary>mzansi_innovation_hub</binary>
|
||||||
|
</provides>
|
||||||
|
|
||||||
|
<releases>
|
||||||
|
<release version="1.0.0" date="2026-02-26"/>
|
||||||
|
</releases>
|
||||||
|
|
||||||
|
<content_rating type="oars-1.1"/>
|
||||||
|
|
||||||
|
<categories>
|
||||||
|
<category>Utility</category>
|
||||||
|
</categories>
|
||||||
|
|
||||||
|
</component>
|
||||||
BIN
mih_ui/mih_app_flatpak/za.co.mzansiinnovationhub.mih.png
Normal file
BIN
mih_ui/mih_app_flatpak/za.co.mzansiinnovationhub.mih.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
55
mih_ui/mih_app_flatpak/za.co.mzansiinnovationhub.mih.yml
Normal file
55
mih_ui/mih_app_flatpak/za.co.mzansiinnovationhub.mih.yml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
id: za.co.mzansiinnovationhub.mih
|
||||||
|
runtime: org.freedesktop.Platform
|
||||||
|
runtime-version: '24.08'
|
||||||
|
sdk: org.freedesktop.Sdk
|
||||||
|
command: mzansi_innovation_hub
|
||||||
|
|
||||||
|
finish-args:
|
||||||
|
- --share=ipc
|
||||||
|
- --share=network # Added for Internet access
|
||||||
|
- --socket=fallback-x11
|
||||||
|
- --socket=wayland
|
||||||
|
- --device=dri
|
||||||
|
# Removed --filesystem=home for better security; add back only if strictly needed.
|
||||||
|
|
||||||
|
modules:
|
||||||
|
- name: mzansi-innovation-hub
|
||||||
|
buildsystem: simple
|
||||||
|
sources:
|
||||||
|
- type: archive
|
||||||
|
url: https://git.mzansi-innovation-hub.co.za/yaso_meth/mih-project/releases/download/linux/mzansi_innovation_hub.tar.gz
|
||||||
|
sha256: b8c383f4d43e2de36b4e6520c9745e3f8e8618bdb9ef6024ad0bf260061137a9
|
||||||
|
# If the tarball contains a top-level folder (like 'bundle'),
|
||||||
|
# flatpak-builder enters it automatically.
|
||||||
|
# If it doesn't, we use the commands below to find them.
|
||||||
|
|
||||||
|
- type: file
|
||||||
|
path: za.co.mzansiinnovationhub.mih.desktop
|
||||||
|
- type: file
|
||||||
|
path: za.co.mzansiinnovationhub.mih.metainfo.xml
|
||||||
|
- type: file
|
||||||
|
path: za.co.mzansiinnovationhub.mih.png
|
||||||
|
|
||||||
|
build-commands:
|
||||||
|
# 1. Create the necessary directories
|
||||||
|
- mkdir -p /app/bin /app/share/applications /app/share/icons/hicolor/256x256/apps /app/share/metainfo
|
||||||
|
|
||||||
|
# 2. Move EVERYTHING from your archive into /app/bin/
|
||||||
|
# We use 'find' to move only the app-related files and avoid the metadata files
|
||||||
|
- |
|
||||||
|
find . -mindepth 1 -maxdepth 2 \
|
||||||
|
! -name "*.desktop" \
|
||||||
|
! -name "*.xml" \
|
||||||
|
! -name "*.png" \
|
||||||
|
! -name "*.yml" \
|
||||||
|
-exec cp -R -t /app/bin/ {} +
|
||||||
|
|
||||||
|
# 3. Ensure the binary is in the right place and executable
|
||||||
|
# If the binary ended up in a subfolder, this moves it to the top of /app/bin
|
||||||
|
- find /app/bin -name "mzansi_innovation_hub" -type f -exec mv {} /app/bin/ \;
|
||||||
|
- chmod +x /app/bin/mzansi_innovation_hub
|
||||||
|
|
||||||
|
# 4. Install Metadata (using the exact local files)
|
||||||
|
- install -Dm644 za.co.mzansiinnovationhub.mih.desktop /app/share/applications/za.co.mzansiinnovationhub.mih.desktop
|
||||||
|
- install -Dm644 za.co.mzansiinnovationhub.mih.png /app/share/icons/hicolor/256x256/apps/za.co.mzansiinnovationhub.mih.png
|
||||||
|
- install -Dm644 za.co.mzansiinnovationhub.mih.metainfo.xml /app/share/metainfo/za.co.mzansiinnovationhub.mih.metainfo.xml
|
||||||
@@ -369,6 +369,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.0"
|
||||||
|
dbus:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dbus
|
||||||
|
sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.12"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -808,6 +816,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
|
geoclue:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: geoclue
|
||||||
|
sha256: c2a998c77474fc57aa00c6baa2928e58f4b267649057a1c76738656e9dbd2a7f
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.1"
|
||||||
geolocator:
|
geolocator:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -832,6 +848,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.13"
|
version: "2.3.13"
|
||||||
|
geolocator_linux:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: geolocator_linux
|
||||||
|
sha256: d64112a205931926f4363bb6bd48f14cb38e7326833041d170615586cd143797
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.4"
|
||||||
geolocator_platform_interface:
|
geolocator_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -904,6 +928,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.2"
|
version: "2.3.2"
|
||||||
|
gsettings:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: gsettings
|
||||||
|
sha256: "1b0ce661f5436d2db1e51f3c4295a49849f03d304003a7ba177d01e3a858249c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.8"
|
||||||
html:
|
html:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: mzansi_innovation_hub
|
name: mzansi_innovation_hub
|
||||||
description: ""
|
description: ""
|
||||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
version: 1.2.6+127
|
version: 1.2.6+130
|
||||||
# version: 1.1.1+97 #--- Updated version for upgrader package testing
|
# version: 1.1.1+97 #--- Updated version for upgrader package testing
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
@@ -29,6 +29,7 @@ dependencies:
|
|||||||
flutter_native_splash: ^2.4.6
|
flutter_native_splash: ^2.4.6
|
||||||
printing: ^5.13.3
|
printing: ^5.13.3
|
||||||
geolocator: ^14.0.1
|
geolocator: ^14.0.1
|
||||||
|
geolocator_linux: ^0.2.4
|
||||||
table_calendar: ^3.1.2
|
table_calendar: ^3.1.2
|
||||||
youtube_player_iframe: ^5.2.0
|
youtube_player_iframe: ^5.2.0
|
||||||
mobile_scanner: ^7.0.1
|
mobile_scanner: ^7.0.1
|
||||||
|
|||||||
Reference in New Issue
Block a user