mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-30 21:05:42 +00:00 
			
		
		
		
	* Remove unused lib/generated/i18n.dart * Use `fvm dart format .` * Add contributing guidelines * Enforce dart format * Add `dart format off` directive to generated files
		
			
				
	
	
		
			180 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| /*
 | |
|  * A set of helper functions to reduce boilerplate code
 | |
|  */
 | |
| 
 | |
| /*
 | |
|  * Simplify a numerical value into a string,
 | |
|  * supressing trailing zeroes
 | |
|  */
 | |
| 
 | |
| import "dart:io";
 | |
| import "package:currency_formatter/currency_formatter.dart";
 | |
| 
 | |
| import "package:one_context/one_context.dart";
 | |
| import "package:url_launcher/url_launcher.dart";
 | |
| import "package:audioplayers/audioplayers.dart";
 | |
| 
 | |
| import "package:inventree/l10.dart";
 | |
| import "package:inventree/widget/snacks.dart";
 | |
| 
 | |
| List<String> debug_messages = [];
 | |
| 
 | |
| void clearDebugMessage() => debug_messages.clear();
 | |
| 
 | |
| int debugMessageCount() {
 | |
|   print("Debug Messages: ${debug_messages.length}");
 | |
|   return debug_messages.length;
 | |
| }
 | |
| 
 | |
| // Check if the debug log contains a given message
 | |
| bool debugContains(String msg, {bool raiseAssert = true}) {
 | |
|   bool result = false;
 | |
| 
 | |
|   for (String element in debug_messages) {
 | |
|     if (element.contains(msg)) {
 | |
|       result = true;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!result) {
 | |
|     print("Debug does not contain expected string: '${msg}'");
 | |
|   }
 | |
| 
 | |
|   if (raiseAssert) {
 | |
|     assert(result);
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| bool isTesting() {
 | |
|   return Platform.environment.containsKey("FLUTTER_TEST");
 | |
| }
 | |
| 
 | |
| bool hasContext() {
 | |
|   try {
 | |
|     return !isTesting() && OneContext.hasContext;
 | |
|   } catch (error) {
 | |
|     return false;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Display a debug message if we are in testing mode, or running in debug mode
 | |
|  */
 | |
| void debug(dynamic msg) {
 | |
|   if (Platform.environment.containsKey("FLUTTER_TEST")) {
 | |
|     debug_messages.add(msg.toString());
 | |
|   }
 | |
| 
 | |
|   print("DEBUG: ${msg.toString()}");
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Simplify string representation of a floating point value
 | |
|  * Basically, don't display fractional component if it is an integer
 | |
|  */
 | |
| String simpleNumberString(double number) {
 | |
|   if (number.toInt() == number) {
 | |
|     return number.toInt().toString();
 | |
|   } else {
 | |
|     return number.toString();
 | |
|   }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Play an audio file from the requested path.
 | |
|  *
 | |
|  * Note: If OneContext module fails the 'hasContext' check,
 | |
|  *       we will not attempt to play the sound
 | |
|  */
 | |
| Future<void> playAudioFile(String path) async {
 | |
|   // Debug message for unit testing
 | |
|   debug("Playing audio file: '${path}'");
 | |
| 
 | |
|   if (!hasContext()) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   final player = AudioPlayer();
 | |
| 
 | |
|   // Specify context options for the audio player
 | |
|   // Ref: https://github.com/inventree/inventree-app/issues/582
 | |
|   player.setAudioContext(
 | |
|     AudioContext(
 | |
|       android: AudioContextAndroid(
 | |
|         usageType: AndroidUsageType.notification,
 | |
|         audioFocus: AndroidAudioFocus.none,
 | |
|       ),
 | |
|       iOS: AudioContextIOS(),
 | |
|     ),
 | |
|   );
 | |
| 
 | |
|   player.play(AssetSource(path));
 | |
| }
 | |
| 
 | |
| // Open an external URL
 | |
| Future<void> openLink(String url) async {
 | |
|   final link = Uri.parse(url);
 | |
| 
 | |
|   try {
 | |
|     await launchUrl(link);
 | |
|   } catch (e) {
 | |
|     showSnackIcon(L10().error, success: false);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Helper function for rendering a money / currency object as a String
 | |
|  */
 | |
| String renderCurrency(double? amount, String currency, {int decimals = 2}) {
 | |
|   if (amount == null || amount.isInfinite || amount.isNaN) return "-";
 | |
| 
 | |
|   currency = currency.trim();
 | |
| 
 | |
|   if (currency.isEmpty) return "-";
 | |
| 
 | |
|   CurrencyFormat fmt =
 | |
|       CurrencyFormat.fromCode(currency.toLowerCase()) ?? CurrencyFormat.usd;
 | |
| 
 | |
|   String value = CurrencyFormatter.format(amount, fmt);
 | |
| 
 | |
|   return value;
 | |
| }
 | |
| 
 | |
| bool isValidNumber(double? value) {
 | |
|   return value != null && !value.isNaN && !value.isInfinite;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Render a "range" of prices between two values.
 | |
|  */
 | |
| String formatPriceRange(
 | |
|   double? minPrice,
 | |
|   double? maxPrice, {
 | |
|   String? currency,
 | |
| }) {
 | |
|   // Account for empty or null values
 | |
|   if (!isValidNumber(minPrice) && !isValidNumber(maxPrice)) {
 | |
|     return "-";
 | |
|   }
 | |
| 
 | |
|   if (isValidNumber(minPrice) && isValidNumber(maxPrice)) {
 | |
|     // Two values are equal
 | |
|     if (minPrice == maxPrice) {
 | |
|       return renderCurrency(minPrice, currency ?? "USD");
 | |
|     } else {
 | |
|       return "${renderCurrency(minPrice, currency ?? "USD")} - ${renderCurrency(maxPrice, currency ?? "USD")}";
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (isValidNumber(minPrice)) {
 | |
|     return renderCurrency(minPrice, currency ?? "USD");
 | |
|   } else if (isValidNumber(maxPrice)) {
 | |
|     return renderCurrency(maxPrice, currency ?? "USD");
 | |
|   } else {
 | |
|     return "-";
 | |
|   }
 | |
| }
 |