From 8912e77b038d9161b7f6579f9d14f4ea8675cbac Mon Sep 17 00:00:00 2001 From: yaso Date: Thu, 9 Jul 2026 14:29:34 +0200 Subject: [PATCH] add install & update MIH Linux --- .../components/call_to_action_buttons.dart | 111 ++--------- .../components/mih_android_store_options.dart | 97 ++++++++++ .../mih_linux_install_instructions.dart | 183 ++++++++++++++++++ .../mih_linux_update_instructions.dart | 151 +++++++++++++++ .../mih_services/mih_install_services.dart | 31 ++- 5 files changed, 464 insertions(+), 109 deletions(-) create mode 100644 mih_ui/lib/mih_packages/about_mih/components/mih_android_store_options.dart create mode 100644 mih_ui/lib/mih_packages/about_mih/components/mih_linux_install_instructions.dart create mode 100644 mih_ui/lib/mih_packages/about_mih/components/mih_linux_update_instructions.dart diff --git a/mih_ui/lib/mih_packages/about_mih/components/call_to_action_buttons.dart b/mih_ui/lib/mih_packages/about_mih/components/call_to_action_buttons.dart index a5c187d3..fe0dd406 100644 --- a/mih_ui/lib/mih_packages/about_mih/components/call_to_action_buttons.dart +++ b/mih_ui/lib/mih_packages/about_mih/components/call_to_action_buttons.dart @@ -1,11 +1,9 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:go_router/go_router.dart'; import 'package:mih_package_toolkit/mih_package_toolkit.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_install_services.dart'; -import 'package:url_launcher/url_launcher.dart'; class CallToActionButtons extends StatefulWidget { const CallToActionButtons({super.key}); @@ -15,16 +13,12 @@ class CallToActionButtons extends StatefulWidget { } class _CallToActionButtonsState extends State { - Future launchSocialUrl(Uri linkUrl) async { - if (!await launchUrl(linkUrl)) { - throw Exception('Could not launch $linkUrl'); - } - } - Widget getInstallButtonText() { final isWebAndroid = kIsWeb && (defaultTargetPlatform == TargetPlatform.android); final isWebIos = kIsWeb && (defaultTargetPlatform == TargetPlatform.iOS); + final isWebLinux = + kIsWeb && (defaultTargetPlatform == TargetPlatform.linux); String btnText = ""; FaIconData platformIcon; if (isWebAndroid) { @@ -33,6 +27,9 @@ class _CallToActionButtonsState extends State { } else if (isWebIos) { btnText = "Install MIH"; platformIcon = FontAwesomeIcons.appStoreIos; + } else if (isWebLinux) { + btnText = "Install MIH"; + platformIcon = FontAwesomeIcons.linux; } else if (MzansiInnovationHub.of(context)!.theme.getPlatform() == "Android") { btnText = "Update MIH"; @@ -40,6 +37,10 @@ class _CallToActionButtonsState extends State { } else if (MzansiInnovationHub.of(context)!.theme.getPlatform() == "iOS") { btnText = "Update MIH"; platformIcon = FontAwesomeIcons.appStoreIos; + } else if (MzansiInnovationHub.of(context)!.theme.getPlatform() == + "Linux") { + btnText = "Update MIH"; + platformIcon = FontAwesomeIcons.linux; } else { btnText = "Install MIH"; platformIcon = FontAwesomeIcons.globe; @@ -76,95 +77,7 @@ class _CallToActionButtonsState extends State { children: [ MihButton( onPressed: () { - if (MzansiInnovationHub.of(context)!.theme.getPlatform() == - "Android") { - showDialog( - context: context, - builder: (context) { - return MihPackageWindow( - fullscreen: false, - windowTitle: "Select Option", - onWindowTapClose: () { - context.pop(); - }, - windowBody: Column( - children: [ - Text( - "Please select the platform you want to install/ Update MIH from", - style: TextStyle( - color: MihColors.secondary(), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 25), - MihButton( - onPressed: () { - launchSocialUrl( - Uri.parse( - "https://play.google.com/store/apps/details?id=za.co.mzansiinnovationhub.mih", - ), - ); - }, - buttonColor: MihColors.green(), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FaIcon( - FontAwesomeIcons.googlePlay, - color: MihColors.primary(), - ), - const SizedBox(width: 10), - Text( - "Play Store", - style: TextStyle( - color: MihColors.primary(), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - const SizedBox( - height: 10, - ), - MihButton( - onPressed: () { - launchSocialUrl( - Uri.parse( - "https://appgallery.huawei.com/app/C113315335?pkgName=za.co.mzansiinnovationhub.mih", - ), - ); - }, - buttonColor: MihColors.green(), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.store, - color: MihColors.primary(), - ), - const SizedBox(width: 10), - Text( - "App Gallery", - style: TextStyle( - color: MihColors.primary(), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ], - ), - ); - }, - ); - } else { - MihInstallServices().installMihTrigger(context); - } + MihInstallServices().installMihTrigger(context); }, buttonColor: MihColors.green(), width: 300, @@ -172,7 +85,7 @@ class _CallToActionButtonsState extends State { ), MihButton( onPressed: () { - launchSocialUrl( + MihInstallServices().launchSocialUrl( Uri.parse( "https://www.youtube.com/playlist?list=PLuT35kJIui0H5kXjxNOZlHoOPZbQLr4qh", ), @@ -201,7 +114,7 @@ class _CallToActionButtonsState extends State { ), MihButton( onPressed: () { - launchSocialUrl( + MihInstallServices().launchSocialUrl( Uri.parse( "https://patreon.com/MzansiInnovationHub?utm_medium=unknown&utm_source=join_link&utm_campaign=creatorshare_creator&utm_content=copyLink", ), diff --git a/mih_ui/lib/mih_packages/about_mih/components/mih_android_store_options.dart b/mih_ui/lib/mih_packages/about_mih/components/mih_android_store_options.dart new file mode 100644 index 00000000..d9fb76b8 --- /dev/null +++ b/mih_ui/lib/mih_packages/about_mih/components/mih_android_store_options.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mih_package_toolkit/mih_package_toolkit.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_install_services.dart'; + +class MihAndroidStoreOptions extends StatefulWidget { + const MihAndroidStoreOptions({super.key}); + + @override + State createState() => _MihAndroidStoreOptionsState(); +} + +class _MihAndroidStoreOptionsState extends State { + @override + Widget build(BuildContext context) { + return MihPackageWindow( + fullscreen: false, + windowTitle: "Select Option", + onWindowTapClose: () { + context.pop(); + }, + windowBody: Column( + children: [ + Text( + "Please select the platform you want to install/ Update MIH from", + style: TextStyle( + color: MihColors.secondary(), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + MihButton( + onPressed: () { + MihInstallServices().launchSocialUrl( + Uri.parse( + "https://play.google.com/store/apps/details?id=za.co.mzansiinnovationhub.mih", + ), + ); + }, + buttonColor: MihColors.green(), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FaIcon( + FontAwesomeIcons.googlePlay, + color: MihColors.primary(), + ), + const SizedBox(width: 10), + Text( + "Play Store", + style: TextStyle( + color: MihColors.primary(), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + const SizedBox( + height: 10, + ), + MihButton( + onPressed: () { + MihInstallServices().launchSocialUrl( + Uri.parse( + "https://appgallery.huawei.com/app/C113315335?pkgName=za.co.mzansiinnovationhub.mih", + ), + ); + }, + buttonColor: MihColors.green(), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.store, + color: MihColors.primary(), + ), + const SizedBox(width: 10), + Text( + "App Gallery", + style: TextStyle( + color: MihColors.primary(), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/mih_ui/lib/mih_packages/about_mih/components/mih_linux_install_instructions.dart b/mih_ui/lib/mih_packages/about_mih/components/mih_linux_install_instructions.dart new file mode 100644 index 00000000..b56b5f54 --- /dev/null +++ b/mih_ui/lib/mih_packages/about_mih/components/mih_linux_install_instructions.dart @@ -0,0 +1,183 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mih_package_toolkit/mih_package_toolkit.dart'; + +class MihLinuxInstallInstructions extends StatefulWidget { + const MihLinuxInstallInstructions({super.key}); + + @override + State createState() => + _MihLinuxInstallInstructionsState(); +} + +class _MihLinuxInstallInstructionsState + extends State { + Widget _buildInstructionStep(BuildContext context, + {required String stepNumber, + required String title, + required String command}) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '$stepNumber. $title', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(fontWeight: FontWeight.w500), + ), + const SizedBox(height: 6), + Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.grey[900], // Dark background for terminal look + borderRadius: BorderRadius.circular(6), + ), + child: Row( + children: [ + Expanded( + child: Text( + command, + style: const TextStyle( + fontFamily: 'Courier', // Monospace font for commands + color: Colors.lightGreenAccent, + fontSize: 13, + ), + ), + ), + IconButton( + icon: const Icon(Icons.copy, color: Colors.grey, size: 18), + onPressed: () { + // Clipboard functionality (Requires: import 'package:flutter/services.dart';) + Clipboard.setData(ClipboardData(text: command)); + ScaffoldMessenger.of(context).showSnackBar( + MihSnackBar( + child: Text('Command copied to clipboard!'), + ), + // const SnackBar( + // content: Text('Command copied to clipboard!')), + ); + }, + tooltip: 'Copy command', + ), + ], + ), + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + return MihPackageWindow( + fullscreen: false, + windowTitle: null, + onWindowTapClose: () { + context.pop(); + }, + windowBody: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header + Center( + child: FaIcon( + FontAwesomeIcons.linux, + color: MihColors.secondary(), + size: 125, + ), + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Get MIH for Linux', + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 12), + + // Description + Text( + 'Download the official MIH desktop application for Linux. Distributed as a sandboxed Flatpak package, it ensures seamless integration and automatic updates across any Linux distribution.', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(height: 1.4), + ), + const SizedBox(height: 16), + + // Prerequisite + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.amber.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: Colors.amber.withOpacity(0.3)), + ), + child: Row( + children: [ + const Icon(Icons.warning_amber_rounded, + color: Colors.amber), + const SizedBox(width: 8), + Expanded( + child: Text( + 'Prerequisite: Ensure Flatpak is installed on your machine.', + style: + Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 16), + + // Instructions Header + Text( + 'Installation Instructions', + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 8), + + // Command 1 + _buildInstructionStep( + context, + stepNumber: '1', + title: 'Add the MIH repository:', + command: + 'flatpak remote-add --if-not-exists mih-fphub https://fphub.mzansi-innovation-hub.co.za/mih-fphub.flatpakrepo', + ), + const SizedBox(height: 12), + + // Command 2 + _buildInstructionStep( + context, + stepNumber: '2', + title: 'Install the application:', + command: + 'flatpak install mih-fphub za.co.mzansiinnovationhub.mih', + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/mih_ui/lib/mih_packages/about_mih/components/mih_linux_update_instructions.dart b/mih_ui/lib/mih_packages/about_mih/components/mih_linux_update_instructions.dart new file mode 100644 index 00000000..ee7a68ea --- /dev/null +++ b/mih_ui/lib/mih_packages/about_mih/components/mih_linux_update_instructions.dart @@ -0,0 +1,151 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mih_package_toolkit/mih_package_toolkit.dart'; + +class MihLinuxUpdateInstructions extends StatefulWidget { + const MihLinuxUpdateInstructions({super.key}); + + @override + State createState() => + _MihLinuxUpdateInstructionsState(); +} + +class _MihLinuxUpdateInstructionsState + extends State { + Widget _buildInstructionStep(BuildContext context, + {required String stepNumber, + required String title, + required String command}) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '$stepNumber $title', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(fontWeight: FontWeight.w500), + ), + const SizedBox(height: 6), + Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.grey[900], // Dark background for terminal look + borderRadius: BorderRadius.circular(6), + ), + child: Row( + children: [ + Expanded( + child: Text( + command, + style: const TextStyle( + fontFamily: 'Courier', // Monospace font for commands + color: Colors.lightGreenAccent, + fontSize: 13, + ), + ), + ), + IconButton( + icon: const Icon(Icons.copy, color: Colors.grey, size: 18), + onPressed: () { + // Clipboard functionality (Requires: import 'package:flutter/services.dart';) + Clipboard.setData(ClipboardData(text: command)); + ScaffoldMessenger.of(context).showSnackBar( + MihSnackBar( + child: Text('Command copied to clipboard!'), + ), + ); + }, + tooltip: 'Copy command', + ), + ], + ), + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + return MihPackageWindow( + fullscreen: false, + windowTitle: null, + onWindowTapClose: () { + context.pop(); + }, + windowBody: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header + Center( + child: FaIcon( + FontAwesomeIcons.linux, + color: MihColors.secondary(), + size: 125, + ), + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Update MIH for Linux', + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 12), + + // Description + Text( + 'Flatpak apps usually update automatically via your system\'s Software Center. To manually force an update via the terminal, use one of the following commands:', + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(height: 1.4), + ), + const SizedBox(height: 16), + + Text( + 'Update Instructions', + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 8), + + // Command 1 + _buildInstructionStep( + context, + stepNumber: '•', + title: 'Update only the MIH app:', + command: 'flatpak update za.co.mzansiinnovationhub.mih', + ), + const SizedBox(height: 12), + + // Command 2 + _buildInstructionStep( + context, + stepNumber: '•', + title: 'Update all Flatpak apps on your system:', + command: 'flatpak update', + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/mih_ui/lib/mih_services/mih_install_services.dart b/mih_ui/lib/mih_services/mih_install_services.dart index 7a59bfe1..7e39a39d 100644 --- a/mih_ui/lib/mih_services/mih_install_services.dart +++ b/mih_ui/lib/mih_services/mih_install_services.dart @@ -1,6 +1,9 @@ import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; +import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_packages/about_mih/components/mih_android_store_options.dart'; +import 'package:mzansi_innovation_hub/mih_packages/about_mih/components/mih_linux_install_instructions.dart'; +import 'package:mzansi_innovation_hub/mih_packages/about_mih/components/mih_linux_update_instructions.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:mzansi_innovation_hub/mih_helpers/mih_install_stub.dart' if (dart.library.js_interop) 'package:mzansi_innovation_hub/mih_helpers/mih_install_web.dart'; @@ -18,11 +21,12 @@ class MihInstallServices { final isWebAndroid = kIsWeb && (defaultTargetPlatform == TargetPlatform.android); final isWebIos = kIsWeb && (defaultTargetPlatform == TargetPlatform.iOS); + final isWebLinux = + kIsWeb && (defaultTargetPlatform == TargetPlatform.linux); if (isWebAndroid) { - launchSocialUrl( - Uri.parse( - "https://play.google.com/store/apps/details?id=za.co.mzansiinnovationhub.mih", - ), + showDialog( + context: context, + builder: (context) => MihAndroidStoreOptions(), ); } else if (isWebIos) { //Show pop up for IOS @@ -33,11 +37,9 @@ class MihInstallServices { ); } else if (MzansiInnovationHub.of(context)!.theme.getPlatform() == "Android") { - //Installed Android App - launchSocialUrl( - Uri.parse( - "https://play.google.com/store/apps/details?id=za.co.mzansiinnovationhub.mih", - ), + showDialog( + context: context, + builder: (context) => MihAndroidStoreOptions(), ); } else if (MzansiInnovationHub.of(context)!.theme.getPlatform() == "iOS") { launchSocialUrl( @@ -45,8 +47,17 @@ class MihInstallServices { "https://apps.apple.com/za/app/mzansi-innovation-hub/id6743310890", ), ); + } else if (isWebLinux) { + showDialog( + context: context, + builder: (context) => MihLinuxInstallInstructions(), + ); } else if (MzansiInnovationHub.of(context)!.theme.getPlatform() == "Linux") { + showDialog( + context: context, + builder: (context) => MihLinuxUpdateInstructions(), + ); } else { //Web triggerWebInstall();