From c1c0f17bee88b819b61a4595c0733e250168fbb8 Mon Sep 17 00:00:00 2001 From: yaso Date: Thu, 23 Jan 2025 14:24:43 +0200 Subject: [PATCH] Create new Mzansi Package Template --- .../mih_package/mih-app_tool_body.dart | 87 +++++++ .../mih_components/mih_package/mih_app.dart | 82 +++++++ .../mih_package/mih_app_action.dart | 38 ++++ .../mih_package/mih_app_alert.dart | 113 +++++++++ .../mih_package/mih_app_tile.dart | 111 +++++++++ .../mih_package/mih_app_tools.dart | 52 +++++ .../mih_package/mih_app_window.dart | 214 ++++++++++++++++++ 7 files changed, 697 insertions(+) create mode 100644 Frontend/lib/mih_components/mih_package/mih-app_tool_body.dart create mode 100644 Frontend/lib/mih_components/mih_package/mih_app.dart create mode 100644 Frontend/lib/mih_components/mih_package/mih_app_action.dart create mode 100644 Frontend/lib/mih_components/mih_package/mih_app_alert.dart create mode 100644 Frontend/lib/mih_components/mih_package/mih_app_tile.dart create mode 100644 Frontend/lib/mih_components/mih_package/mih_app_tools.dart create mode 100644 Frontend/lib/mih_components/mih_package/mih_app_window.dart diff --git a/Frontend/lib/mih_components/mih_package/mih-app_tool_body.dart b/Frontend/lib/mih_components/mih_package/mih-app_tool_body.dart new file mode 100644 index 00000000..d0f2da0c --- /dev/null +++ b/Frontend/lib/mih_components/mih_package/mih-app_tool_body.dart @@ -0,0 +1,87 @@ +import 'package:Mzansi_Innovation_Hub/main.dart'; +import 'package:flutter/material.dart'; + +class MihAppToolBody extends StatefulWidget { + final bool borderOn; + final Widget bodyItem; + const MihAppToolBody({ + super.key, + required this.borderOn, + required this.bodyItem, + }); + + @override + State createState() => _MihAppToolBodyState(); +} + +class _MihAppToolBodyState extends State { + late double _innerBodyPadding; + double getHorizontalPaddingSize(Size screenSize) { + if (MzanziInnovationHub.of(context)!.theme.screenType == "desktop") { + if (widget.borderOn) { + return 10; + } else { + return 0; + } + } else { + // mobile + if (widget.borderOn) { + return 10; + } else { + return 0; + } + } + } + + double getVerticalPaddingSize(Size screenSize) { + // mobile + if (widget.borderOn) { + return 10; + } else { + return 0; + } + } + + Decoration? getBoader() { + if (widget.borderOn) { + _innerBodyPadding = 10.0; + return BoxDecoration( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + borderRadius: BorderRadius.circular(25.0), + border: Border.all( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + width: 3.0), + ); + } else { + _innerBodyPadding = 0.0; + return BoxDecoration( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + borderRadius: BorderRadius.circular(25.0), + border: Border.all( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + width: 3.0), + ); + } + } + + @override + Widget build(BuildContext context) { + Size screenSize = MediaQuery.sizeOf(context); + + return Padding( + padding: EdgeInsets.only( + left: getHorizontalPaddingSize(screenSize), + right: getHorizontalPaddingSize(screenSize), + bottom: getVerticalPaddingSize(screenSize), + top: 0, + ), + child: Container( + decoration: getBoader(), + child: Padding( + padding: EdgeInsets.all(_innerBodyPadding), + child: widget.bodyItem, + ), + ), + ); + } +} diff --git a/Frontend/lib/mih_components/mih_package/mih_app.dart b/Frontend/lib/mih_components/mih_package/mih_app.dart new file mode 100644 index 00000000..7c67609a --- /dev/null +++ b/Frontend/lib/mih_components/mih_package/mih_app.dart @@ -0,0 +1,82 @@ +import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih-app_tool_body.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih_app_action.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih_app_tools.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_swipe_detector/flutter_swipe_detector.dart'; + +// ignore: must_be_immutable +class MihApp extends StatefulWidget { + final MihAppAction appActionButton; + final MihAppTools appTools; + final List appBody; + int selectedbodyIndex; + final onIndexChange; + MihApp({ + super.key, + required this.appActionButton, + required this.appTools, + required this.appBody, + required this.selectedbodyIndex, + required this.onIndexChange, + }); + + @override + State createState() => _MihAppState(); +} + +class _MihAppState extends State { + @override + Widget build(BuildContext context) { + Size screenSize = MediaQuery.of(context).size; + return Scaffold( + body: SafeArea( + child: Container( + width: screenSize.width, + height: screenSize.height, + //color: Colors.black, + child: Column( + children: [ + Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + widget.appActionButton, + Flexible(child: widget.appTools), + ], + ), + Expanded( + child: SwipeDetector( + onSwipeLeft: (offset) { + if (widget.selectedbodyIndex < + widget.appTools.tools.length - 1) { + setState(() { + widget.selectedbodyIndex += 1; + widget.onIndexChange(widget.selectedbodyIndex); + }); + } + // print("swipe left"); + }, + onSwipeRight: (offset) { + if (widget.selectedbodyIndex > 0) { + setState(() { + widget.selectedbodyIndex -= 1; + widget.onIndexChange(widget.selectedbodyIndex); + }); + } + // print("swipe right"); + }, + child: Row( + children: [ + Expanded( + child: widget.appBody[widget.selectedbodyIndex], + ) + ], + ), + )), + ], + ), + ), + ), + ); + } +} diff --git a/Frontend/lib/mih_components/mih_package/mih_app_action.dart b/Frontend/lib/mih_components/mih_package/mih_app_action.dart new file mode 100644 index 00000000..154e0ae8 --- /dev/null +++ b/Frontend/lib/mih_components/mih_package/mih_app_action.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +class MihAppAction extends StatefulWidget { + final void Function()? onTap; + final double iconSize; + final Widget icon; + const MihAppAction({ + super.key, + required this.icon, + required this.iconSize, + required this.onTap, + }); + + @override + State createState() => _MihAppActionState(); +} + +class _MihAppActionState extends State { + @override + void dispose() { + super.dispose(); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return IconButton( + iconSize: widget.iconSize, + padding: const EdgeInsets.all(0), + onPressed: widget.onTap, + icon: widget.icon, + ); + } +} diff --git a/Frontend/lib/mih_components/mih_package/mih_app_alert.dart b/Frontend/lib/mih_components/mih_package/mih_app_alert.dart new file mode 100644 index 00000000..8db477c4 --- /dev/null +++ b/Frontend/lib/mih_components/mih_package/mih_app_alert.dart @@ -0,0 +1,113 @@ +import 'package:Mzansi_Innovation_Hub/main.dart'; +import 'package:flutter/material.dart'; + +class MihAppAlert extends StatefulWidget { + final Widget alertIcon; + final String alertTitle; + final Widget alertBody; + final Color alertColour; + const MihAppAlert({ + super.key, + required this.alertIcon, + required this.alertTitle, + required this.alertBody, + required this.alertColour, + }); + + @override + State createState() => _MihAppAlertState(); +} + +class _MihAppAlertState extends State { + late double popUpWidth; + late double? popUpheight; + late double popUpTitleSize; + late double popUpSubtitleSize; + late double popUpBodySize; + late double popUpIconSize; + late double popUpPaddingSize; + Size? size; + + void checkScreenSize() { + if (MzanziInnovationHub.of(context)!.theme.screenType == "desktop") { + setState(() { + popUpWidth = (size!.width / 4) * 2; + popUpheight = null; + popUpTitleSize = 25.0; + popUpSubtitleSize = 20.0; + popUpBodySize = 15; + popUpPaddingSize = 25.0; + popUpIconSize = 100; + }); + } else { + setState(() { + popUpWidth = size!.width - (size!.width * 0.1); + popUpheight = null; + popUpTitleSize = 20.0; + popUpSubtitleSize = 18.0; + popUpBodySize = 15; + popUpPaddingSize = 15.0; + popUpIconSize = 100; + }); + } + } + + @override + Widget build(BuildContext context) { + size = MediaQuery.of(context).size; + checkScreenSize(); + return Dialog( + child: Stack( + children: [ + Container( + padding: EdgeInsets.all(popUpPaddingSize), + width: popUpWidth, + height: popUpheight, + decoration: BoxDecoration( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + borderRadius: BorderRadius.circular(25.0), + border: Border.all(color: widget.alertColour, width: 5.0), + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + widget.alertIcon, + //const SizedBox(height: 5), + Text( + widget.alertTitle, + textAlign: TextAlign.center, + style: TextStyle( + color: widget.alertColour, + fontSize: popUpTitleSize, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 15), + widget.alertBody, + const SizedBox(height: 10), + ], + ), + ), + ), + Positioned( + top: 5, + right: 5, + width: 50, + height: 50, + child: IconButton( + onPressed: () { + Navigator.pop(context); + }, + icon: Icon( + Icons.close, + color: widget.alertColour, + size: 35, + ), + ), + ), + ], + ), + ); + } +} diff --git a/Frontend/lib/mih_components/mih_package/mih_app_tile.dart b/Frontend/lib/mih_components/mih_package/mih_app_tile.dart new file mode 100644 index 00000000..52ed41aa --- /dev/null +++ b/Frontend/lib/mih_components/mih_package/mih_app_tile.dart @@ -0,0 +1,111 @@ +import 'package:Mzansi_Innovation_Hub/main.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih_app_window.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_yt_video_player.dart'; +import 'package:flutter/material.dart'; + +class MihAppTile extends StatefulWidget { + final String appName; + final String? ytVideoID; + final Widget appIcon; + final void Function() onTap; + final double iconSize; + final Color primaryColor; + final Color secondaryColor; + const MihAppTile({ + super.key, + required this.onTap, + required this.appName, + this.ytVideoID, + required this.appIcon, + required this.iconSize, + required this.primaryColor, + required this.secondaryColor, + }); + + @override + State createState() => _MihAppTileState(); +} + +class _MihAppTileState extends State { + void displayHint() { + if (widget.ytVideoID != null) { + showDialog( + context: context, + builder: (context) { + return MihAppWindow( + fullscreen: false, + windowTitle: widget.appName, + windowTools: const [], + onWindowTapClose: () { + Navigator.pop(context); + }, + windowBody: [ + MIHYTVideoPlayer( + videoYTLink: widget.ytVideoID!, + ), + ], + ); + }, + ); + } + } + + @override + Widget build(BuildContext context) { + double borderRadius = widget.iconSize * 0.25; + return SizedBox( + width: widget.iconSize, + child: Container( + alignment: Alignment.topCenter, + // color: Colors.black, + // constraints: BoxConstraints(), + child: Column( + children: [ + AnimatedContainer( + //alignment: Alignment.center, + width: widget.iconSize, + height: widget.iconSize, + duration: const Duration(seconds: 2), + child: Material( + color: widget.primaryColor, + // shadowColor: + // MzanziInnovationHub.of(context)!.theme.secondaryColor(), + // elevation: 5, + borderRadius: BorderRadius.circular(borderRadius), + child: InkWell( + borderRadius: BorderRadius.circular(borderRadius), + // ho + onTap: widget.onTap, + onLongPress: () { + displayHint(); + }, + // hoverDuration: , + splashColor: + MzanziInnovationHub.of(context)!.theme.highlightColor(), + highlightColor: + MzanziInnovationHub.of(context)!.theme.highlightColor(), + child: FittedBox(child: widget.appIcon), + ), + ), + ), + const SizedBox(height: 10), + FittedBox( + child: Text( + widget.appName, + textAlign: TextAlign.center, + // softWrap: true, + // overflow: TextOverflow.visible, + style: TextStyle( + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + fontSize: 40.0, + fontWeight: FontWeight.bold, + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/Frontend/lib/mih_components/mih_package/mih_app_tools.dart b/Frontend/lib/mih_components/mih_package/mih_app_tools.dart new file mode 100644 index 00000000..b4907a7c --- /dev/null +++ b/Frontend/lib/mih_components/mih_package/mih_app_tools.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; + +// ignore: must_be_immutable +class MihAppTools extends StatefulWidget { + final Map tools; + int selcetedIndex; + MihAppTools({ + super.key, + required this.tools, + required this.selcetedIndex, + }); + + @override + State createState() => _MihAppToolsState(); +} + +class _MihAppToolsState extends State { + List getTools() { + List temp = []; + int index = 0; + widget.tools.forEach((icon, onTap) { + temp.add( + Visibility( + visible: widget.selcetedIndex != index, + child: IconButton( + onPressed: onTap, + icon: icon, + ), + ), + ); + temp.add( + Visibility( + visible: widget.selcetedIndex == index, + child: IconButton.filled( + onPressed: onTap, + icon: icon, + ), + ), + ); + index += 1; + }); + return temp; + } + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: getTools(), + ); + } +} diff --git a/Frontend/lib/mih_components/mih_package/mih_app_window.dart b/Frontend/lib/mih_components/mih_package/mih_app_window.dart new file mode 100644 index 00000000..da0aa305 --- /dev/null +++ b/Frontend/lib/mih_components/mih_package/mih_app_window.dart @@ -0,0 +1,214 @@ +import 'package:flutter/material.dart'; +import '../../main.dart'; + +class MihAppWindow extends StatefulWidget { + final String windowTitle; + final List windowBody; + final List windowTools; + final void Function() onWindowTapClose; + final bool fullscreen; + const MihAppWindow({ + super.key, + required this.fullscreen, + required this.windowTitle, + required this.windowTools, + required this.onWindowTapClose, + required this.windowBody, + }); + + @override + State createState() => _MihAppWindowState(); +} + +class _MihAppWindowState extends State { + late double windowTitleSize; + late double horizontralWindowPadding; + late double vertticalWindowPadding; + late double windowWidth; + late double windowHeight; + late double width; + late double height; + + void checkScreenSize() { + // print("screen width: $width"); + // print("screen height: $height"); + if (MzanziInnovationHub.of(context)!.theme.screenType == "desktop") { + setState(() { + windowTitleSize = 25; + horizontralWindowPadding = width / 7; + vertticalWindowPadding = 25; + windowWidth = width; + windowHeight = height; + }); + } else { + setState(() { + windowTitleSize = 20; + horizontralWindowPadding = 10; + vertticalWindowPadding = 10; + windowWidth = width; + windowHeight = height; + }); + } + } + + Widget getWidnowClose() { + return Container( + alignment: Alignment.centerRight, + child: IconButton( + onPressed: widget.onWindowTapClose, + icon: Icon( + Icons.close, + color: MzanziInnovationHub.of(context)!.theme.errorColor(), + size: 35, + ), + ), + ); + } + + Widget getWidnowTools() { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: widget.windowTools, + ); + } + + Widget getWidnowTitle() { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: Text( + widget.windowTitle, + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + fontSize: windowTitleSize, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ); + } + + Widget getWidnowHeader() { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + getWidnowTools(), + Expanded( + flex: 2, + child: getWidnowTitle(), + ), + getWidnowClose(), + ], + ); + } + + Widget getWidnowBody() { + if (widget.fullscreen) { + return Expanded( + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: widget.windowBody, + ), + ), + ); + } else { + return Padding( + padding: const EdgeInsets.all(10.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: widget.windowBody, + ), + ); + } + } + + Widget createWindow(Widget header, Widget body) { + Widget visibleItems; + if (widget.fullscreen) { + visibleItems = Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + header, + //const Divider(), + body, + ], + ); + } else { + visibleItems = SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + header, + //const Divider(), + body, + ], + ), + ); + } + return Dialog( + insetPadding: EdgeInsets.symmetric( + horizontal: horizontralWindowPadding, + vertical: vertticalWindowPadding, + ), + insetAnimationCurve: Easing.emphasizedDecelerate, + insetAnimationDuration: Durations.short1, + child: Container( + //padding: const EdgeInsets.all(10), + width: windowWidth, + //height: windowHeight, + decoration: BoxDecoration( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + borderRadius: BorderRadius.circular(25.0), + border: Border.all( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + width: 5.0), + ), + child: visibleItems, + ), + ); + } + + @override + void dispose() { + super.dispose(); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + var size = MediaQuery.of(context).size; + setState(() { + width = size.width; + height = size.height; + }); + checkScreenSize(); + return createWindow( + getWidnowHeader(), + getWidnowBody(), + ); + } +}