package_flutter_env 0.0.15+1 copy "package_flutter_env: ^0.0.15+1" to clipboard
package_flutter_env: ^0.0.15+1 copied to clipboard

Using MIAppBarWidget to create a custom app bar.

Custom script for generating environment-specific code for different platforms #

Features #

The flutter_env.dart file appears to be a custom script for generating environment-specific code for different platforms (Dart, Objective-C, and Gradle for Android). It reads from an environment file (.env by default), and generates code based on the key-value pairs in the environment file.

Here's a basic usage guide:

  1. Create an environment file: Create a .env file in your project root (or specify a different file using the envfile argument). This file should contain key-value pairs, one per line, like this:
    API_KEY=123456
    BASE_URL=https://api.example.com

2.Run the script: You can run the DotENV class with the command-line arguments. For example:

    void main(List<String> args) {
    DotENV(args);
    }

You can pass arguments to specify the platform (platform), the environment file (envfile), and the directory name (dirname). If not specified, it will use default values.

3.Generated code: The script will generate a Dart file (lib/env.dart by default) with a class ENV that contains static string properties for each key-value pair in the environment file. For example:

    class ENV {
        static String API_KEY = "123456";
        static String BASE_URL = "https://api.example.com";
    }

You can then import this file in your Flutter code and access the environment variables like this: ENV.API_KEY.

Please note that this is a basic guide and the actual usage may vary depending on your project setup and requirements. Also, remember to exclude your environment files from version control to avoid committing sensitive data.

Unit Test Command #

At the root of the project, run the following command:

 flutter  test test/dotenv_test.dart

Generate the env.dart file #

At the root of the example project, run the following command: like: /Users/danli/Desktop/2024/packages/package_flutter_env/example Because test is the development environment, the generated file is in the lib folder.

    flutter test test/env_test.dart
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:widgetbook/widgetbook.dart';
import 'package:color_cards/color_common.dart';
import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook;

// Generated directories file (created by widgetbook_generator).
// Run: `flutter pub run build_runner build --delete-conflicting-outputs`
// to generate `lib/main.directories.g.dart` which exposes `directories`.
import 'main.directories.g.dart' as generated;

void main() => runApp(const WidgetbookApp());

@widgetbook.App()
class WidgetbookApp extends StatelessWidget {
  const WidgetbookApp({super.key});

  @override
  Widget build(BuildContext context) {
    // Use generated directories from `main.directories.g.dart`.
    return Widgetbook.material(directories: generated.directories);
  }
}

@widgetbook.UseCase(name: 'Blue', type: ColorGrid)
Widget buildBlueAll(BuildContext context) {
  return ColorGrid(
    title: 'Blue',
    colors: {'blueMedium': BlueColor.blueMedium, 'blueDark': BlueColor.blueDark, 'bluelight1': BlueColor.bluelight1, 'bluelight2': BlueColor.bluelight2},
  );
}

@widgetbook.UseCase(name: 'Green', type: ColorGrid)
Widget buildGreenAll(BuildContext context) {
  return ColorGrid(
    title: 'Green',
    colors: {'greenlight1': GreenColor.greenlight1, 'greenlight2': GreenColor.greenlight2, 'greenMedium': GreenColor.greenMedium, 'greenDark': GreenColor.greenDark},
  );
}

// Sorting options for the color grid. Note: `luminance` sorts from
// light -> dark (descending luminance) which is typically most
// useful when you want the brightest colors first.
enum ColorSort { none, name, hex, luminance, hue }

// Helper: compute relative luminance (0..1) for sorting by brightness
double _luminance(Color c) {
  // Use integer component accessors to avoid ambiguity and ensure
  // consistent behavior across SDK versions.
  final r = c.red / 255.0;
  final g = c.green / 255.0;
  final b = c.blue / 255.0;
  double chan(double x) => x <= 0.03928 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4).toDouble();
  return 0.2126 * chan(r) + 0.7152 * chan(g) + 0.0722 * chan(b);
}

// Helper: convert rgb -> hsl (h in 0..1)
Map<String, double> _rgbToHsl(Color c) {
  final r = c.red / 255.0;
  final g = c.green / 255.0;
  final b = c.blue / 255.0;
  final maxv = [r, g, b].reduce((a, b) => a > b ? a : b);
  final minv = [r, g, b].reduce((a, b) => a < b ? a : b);
  final l = (maxv + minv) / 2.0;
  double h = 0.0, s = 0.0;
  final d = maxv - minv;
  if (d != 0) {
    s = l > 0.5 ? d / (2.0 - maxv - minv) : d / (maxv + minv);
    if (maxv == r) {
      h = (g - b) / d + (g < b ? 6 : 0);
    } else if (maxv == g) {
      h = (b - r) / d + 2;
    } else {
      h = (r - g) / d + 4;
    }
    h /= 6.0;
  }
  return {'h': h, 's': s, 'l': l};
}

// Convert Color to 32-bit ARGB int (replacement for deprecated `.value`).
int colorToArgb(Color c) => (c.alpha << 24) | (c.red << 16) | (c.green << 8) | c.blue;

class ColorGrid extends StatefulWidget {
  final String title;
  final Map<String, Color> colors;
  final ColorSort sort;

  const ColorGrid({super.key, required this.title, required this.colors, this.sort = ColorSort.luminance});

  @override
  State<ColorGrid> createState() => _ColorGridState();
}

class _ColorGridState extends State<ColorGrid> {
  final TextEditingController _searchController = TextEditingController();
  String _query = '';

  @override
  void initState() {
    super.initState();
    _searchController.addListener(() {
      setState(() => _query = _searchController.text.trim());
    });
  }

  @override
  void dispose() {
    _searchController.dispose();
    super.dispose();
  }

  String _hex(Color c) => '#${colorToArgb(c).toRadixString(16).toUpperCase().padLeft(8, '0')}';

  // Normalize user query and hex strings for matching
  String _normalizeHexLike(String s) {
    var t = s.toUpperCase();
    t = t.replaceAll('#', '');
    if (t.startsWith('0X')) t = t.substring(2);
    // If user provided 6-digit hex, expand to include alpha FF prefix so it matches our ARGB output
    if (t.length == 6) t = 'FF$t';
    return t;
  }

  bool _matchesQuery(String name, Color color) {
    if (_query.isEmpty) return true;
    final q = _query.toUpperCase();
    // Match name
    if (name.toUpperCase().contains(q)) return true;
    // Match hex formats like 0xFF4A90A4, #FF4A90A4, #4A90A4, or 4A90A4
    final normalizedQ = _normalizeHexLike(q);
    final hex = _hex(color).replaceAll('#', ''); // ARGB uppercased
    if (hex.contains(normalizedQ)) return true;
    return false;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('${widget.title} Colors')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            // Search field
            Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _searchController,
                    decoration: const InputDecoration(prefixIcon: Icon(Icons.search), hintText: 'Search by name or hex (e.g. 0xFF4A90A4, #4A90A4)'),
                  ),
                ),
                if (_query.isNotEmpty)
                  IconButton(
                    icon: const Icon(Icons.clear),
                    onPressed: () {
                      _searchController.clear();
                    },
                  ),
              ],
            ),
            const SizedBox(height: 12),
            Expanded(
              child: LayoutBuilder(
                builder: (context, constraints) {
                  // Choose an itemWidth that looks good for your cards; smaller -> more columns
                  const double itemWidth = 200;
                  int columns = (constraints.maxWidth / itemWidth).floor();
                  if (columns < 1) columns = 1;
                  if (columns > 12) columns = 12; // upper limit to avoid extreme layouts

                  // Create a sortable list of entries, then apply the selected sort
                  final entries = widget.colors.entries.where((e) => _matchesQuery(e.key, e.value)).toList();
                  switch (widget.sort) {
                    case ColorSort.name:
                      entries.sort((a, b) => a.key.compareTo(b.key));
                      break;
                    case ColorSort.hex:
                      entries.sort((a, b) => colorToArgb(a.value).compareTo(colorToArgb(b.value)));
                      break;
                    case ColorSort.luminance:
                      // Sort from light -> dark (higher luminance first)
                      entries.sort((a, b) => _luminance(b.value).compareTo(_luminance(a.value)));
                      break;
                    case ColorSort.hue:
                      entries.sort((a, b) => _rgbToHsl(a.value)['h']!.compareTo(_rgbToHsl(b.value)['h']!));
                      break;
                    case ColorSort.none:
                      break;
                  }

                  return GridView.count(
                    crossAxisCount: columns,
                    childAspectRatio: 3,
                    crossAxisSpacing: 12,
                    mainAxisSpacing: 12,
                    children: entries.map((e) => _colorTile(e.key, e.value)).toList(),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _colorTile(String name, Color color) {
    return Container(
      decoration: BoxDecoration(borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.grey.shade300)),
      child: Row(
        children: [
          Container(
            width: 72,
            height: double.infinity,
            decoration: BoxDecoration(color: color, borderRadius: const BorderRadius.only(topLeft: Radius.circular(8), bottomLeft: Radius.circular(8))),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(name, style: const TextStyle(fontWeight: FontWeight.bold)),
                const SizedBox(height: 6),
                Text(_hex(color), style: const TextStyle(color: Colors.black54)),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
1
likes
0
points
27
downloads

Publisher

unverified uploader

Weekly Downloads

Using MIAppBarWidget to create a custom app bar.

Homepage

License

unknown (license)

Dependencies

flutter, path

More

Packages that depend on package_flutter_env