패키지, 저장소 및 앱 카테고리 검색

패키지 상세v5.15.0

flutter_chen_common

Flutter 공통 패키지는 개발자가 아름답고 기능이 풍부한 모바일 애플리케이션 인터페이스를 빠르게 구축할 수 있도록 설계되었습니다.

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
930
좋아요
25
Pub 점수
160

패키지 설치

flutter pub add flutter_chen_common

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

시각적으로 매력적이고 기능이 풍부한 모바일 애플리케이션 개발을 가속화하기 위해 재사용 가능한 UI 컴포넌트, 유틸리티 및 스타일링 도구의 컬렉션을 제공하는 플러터 패키지입니다. 일관성과 사용 편의성을 고려하여 설계되었으며, 안드로이드, iOS, 웹, macOS, Windows, 리눅스 플랫폼에서 일반적인 작업을 간소화하는 사전 구축된 위젯과 보조 도구를 제공합니다. 디자인 일관성을 유지하면서 봐일러플레이트 코드를 줄이고자 하는 개발자에게 이상적입니다.

사용 사례

  • 빠른 UI 프로토타이핑
  • 크로스플랫폼 앱 개발
  • 일관된 디자인 시스템 구현
  • 반복적인 위젯 코드 줄이기
  • 테마 및 스타일 관리 간소화

주요 기능

  • 사전에 구성된 사용자 정의 가능한 위젯
  • 크로스 플랫폼 호환성
  • 테마 및 스타일 유틸리티
  • 재사용 가능한 UI 컴포넌트
  • 경량이고 모듈러한 디자인

적합한 대상

  • 초보자에서 중급자까지의 Flutter 개발자
  • 디자인 일관성을 우선시하는 팀
  • 빠른 반복이 필요한 프로젝트
  • 다중 플랫폼을 대상으로 하는 앱
  • 반복 코드를 최소화하고자 하는 개발자

고려 사항

  • 매우 특정한 디자인에 맞춰 사용자 정의가 필요할 수 있습니다
  • 목록에 없는 외부 종속성에 의존합니다
  • 기본 사용법 외에 문서가 제한적
  • 매우 가벼운 앱에는 적합하지 않습니다
  • 더 큰 애플리케이션 컨텍스트 내에서 사용하는 것이 가장 좋습니다

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

Flutter Chen Common

Pub Version License

Overview

English | 中文

Flutter Chen Common is a feature-rich Flutter utility library that provides a one-stop solution for app development.

  • Customizable theme system
  • Enterprise-grade networking
  • Enterprise-grade logging
  • High-quality common widgets
  • Handy utilities and extensions
  • Smart refresh list solution
  • Ready-to-use common popups
  • Unified multi-state layout
  • Context-free global Toast

Features

  • 🎨 Theme system: configure colors, corners, spacing via ThemeExtension
  • 🌍 Internationalization: recommend official Flutter localization (built-in module deprecated)
  • ⚡ Priority overrides: global configuration + per-component overrides
  • 📱 Adaptive design: perfect fit for iOS/Material guidelines
  • 🔥 Enterprise-grade modules: logging/networking/security out of the box

Documentation

Core
  • Networking – Structured logs, retries, token refresh
  • Logging – File logging, filters, custom outputs
  • Network Debug - The network request debugging module provides lightweight packet capture functionality, visual logs, and more.
  • Theme – Customizable theme with light/dark support
UI Components
Online Demo

Quick Start

Install

Add dependency in pubspec.yaml:

dependencies:
  flutter_chen_common: latest version

Run:

flutter pub get
Initialization
final navigatorKey = GlobalKey<NavigatorState>();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // shared_preferences
  await SpUtil.init();
  // Logging
  Directory dir = await getApplicationDocumentsDirectory();
  await Log.init(
    LogConfig(
      retentionDays: 3,
      enableFileLog: true,
      logLevel: LogLevel.all,
      recordLevel: LogLevel.info,
      output: const [],
      printer: PrettyPrinter(dateTimeFormat: DateTimeFormat.dateAndTime),
      logDirectory: kIsWeb ? null : Directory('${dir.path}/logs'),
    ),
  );
  // Networking
  HttpClient.init(
    config: HttpConfig(
      baseUrl: 'https://api.example.com',
      connectTimeout: const Duration(seconds: 30),
      receiveTimeout: const Duration(seconds: 30),
      sendTimeout: const Duration(seconds: 30),
      commonHeaders: () => {"Authorization": SpUtil.getString('token')},
      interceptors: [CustomInterceptor()]
      enableLog: true,
      enableToken: true,
      maxRetries: 3,
      getToken: () => "token",
      onRefreshToken: () async {
        return "new_token";
      },
      onRefreshTokenFailed: () async {
        Log.d("Log in again");
      },
   ),
  );
  // Global context for overlays
  ComContext.init(navigatorKey);
  // Global Toast config (optional)
  ComToast.init(
    config: const ComToastConfig(
      duration: Duration(seconds: 2),
      position: ComToastPosition.center,
    ),
    builder: ComToastWidgetBuilder(
      success: const ComToastConfig(
        iconWidget:
        Icon(Icons.check_circle, color: Color(0xFF10B981), size: 20),
      ),
      error: const ComToastConfig(
        iconWidget: Icon(Icons.cancel, color: Color(0xFFEF4444), size: 20),
      ),
      warning: const ComToastConfig(
        iconWidget:
        Icon(Icons.priority_high, color: Color(0xFFF59E0B), size: 20),
      ),
      info: const ComToastConfig(
        iconWidget:
        Icon(Icons.info_outline, color: Color(0xFF3B82F6), size: 20),
      ),
      loading: ComToastConfig(
        builder: (ctx) => const ComContainer(
          width: 120,
          child: ComLoading(),
        ),
        clickThrough: false,
        duration: Duration.zero,
      ),
    ),
  );

  await ComDebugManager.instance.init(
    dio: HttpClient.instance.dio,
    comDebugConfig: ComDebugConfig(
      enabled: Env.env != EnvEnum.prod,
      maxLogCount: 100, // 最大日志缓存数量
      sanitize: (log) {
        // 敏感数据脱敏示例
        if (log.request?.headers.containsKey('Authorization') ?? false) {
          log.request?.headers['Authorization'] = '***';
        }
        return log;
      },
    ));
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ComConfiguration(
      config: ComConfig.defaults().copyWith(
        emptyWidget: CustomEmptyWidget(), // example
        loadingWidget: CustomLoading(),   // example
      ),
      child: MaterialApp(
		    navigatorKey: navigatorKey,
        builder: (context, child) {
          ComNetworkLogger.show(context);
          child = ComToastBuilder()(context, child);
          return child;
        },
        navigatorObservers: [ComToastNavigatorObserver()],
        theme: ThemeData.light().copyWith(
          extensions: [ComTheme.light()],
        ),
        darkTheme: ThemeData.dark().copyWith(
          extensions: [ComTheme.dark()],
        ),
        home: MainPage(),
        localizationsDelegates: const [ // official localization
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          GlobalCupertinoLocalizations.delegate,
        ],
        supportedLocales: const [
          Locale('zh', 'CN'),
          Locale('en', 'US'),
        ],
      ),
    );
  }
}
🌐 Networking
HttpClient.instance.request(
  "/api",
  method: HttpMethod.post,
  fromJson: (json) => User.fromJson(json),
  showLoading: true,
)
HttpClient.instance.get("/api");
HttpClient.instance.post("/api");
HttpClient.instance.put("/api");
HttpClient.instance.patch("/api");
HttpClient.instance.delete("/api");
HttpClient.instance.uploadFile("/api","filePath");
HttpClient.instance.downloadFile("/api", "savePath");

// HttpConfig key fields:
// baseUrl, connectTimeout, receiveTimeout, sendTimeout,
// commonHeaders(): Map<String, dynamic>,
// interceptors: List<Interceptor>,
// enableLog, enableToken, enableRetry,
// maxRetries, retriesDelay,
// getToken(), onRefreshToken(), onRefreshTokenFailed()

// Sample log output
┌─────────────────────────────────────────────────────────────────────────────
│ ✅ [HTTP] 2025-04-05 23:30:29 Request sent [Duration] 88ms
│ Request: 200 GET http://www.weather.com.cn/data/sk/101010100.html?xxxx=xxxx
│ Headers: {"token":"xxxxx","content-type":"application/json"}
│ Query: {"xxxx":"xxxx"}
│ Response: {"weatherinfo":{"city":"北京","cityid":"101010100","WD":"东南风"}}
└──────────────────────────────────────────────────────────────────────────────
📝 Logging
Log.d("debug message");
Log.i("info message");
Log.w("warning message");
Log.e("error message");
Log.console("console message printed fully without prefix");
final Directory dir = await Log.getLogDir();

class LogConfig {
  final int retentionDays;
  final bool enableFileLog;
  final LogLevel logLevel;
  final LogLevel recordLevel;
  final List<LogOutput>? output;
  final Directory? logDirectory;

  const LogConfig({
    this.retentionDays = 3,
    this.enableFileLog = true,
    this.logLevel = LogLevel.all,
    this.recordLevel = LogLevel.info,
    this.output,
		this.logDirectory,
  });
}

class SentryOutput extends LogOutput {
  @override
  void output(OutputEvent event) {
    if (event.level.value >= LogLevel.error.value) {
      Sentry.captureException(
        event.error,
        stackTrace: event.stackTrace,
        tags: {'log_level': event.level.name},
      );
    }
  }
}

Log.init(LogConfig(
  output: [SentryOutput()]
));

Utils

File Description
clipboard_util.dart Clipboard
file_util.dart File operations
keyboard_util.dart Keyboard helpers
platform_util.dart Platform detection
platform_util_web.dart Web platform helpers
sp_util.dart Local storage
utils.dart Utils entry

Widgets

Basic
File Description
base_widget.dart Base (multi-state)
com_loading.dart Loading widget
Functional
File Description
com_marquee.dart Marquee
com_popup_menu.dart Popup menu
Refresh
File Description
back_top_widget.dart Back to top
refresh_controller.dart Refresh controller
refresh_interface.dart Refresh interface
refresh_state.dart Refresh state
refresh_strategy.dart Refresh strategy
refresh_widget.dart Smart refresh

Theme

Built-in
Name Example
Light Theme ComTheme.light
Dark Theme ComTheme.dark
Configurable
ComTheme(
  shapes: ComShapes.standard,
  spacing: ComSpacing.standard,
  success: Colors.green.shade600,
  error: Colors.red.shade600,
  warning: Colors.orange.shade600,
  link: Colors.blue.shade600,
)

Internationalization

Built-in i18n module is deprecated. Use Flutter official flutter_localizations + intl.

Global State Layout

// Global or local configuration
ComConfiguration(
  config: ComConfig.defaults().copyWith(
    emptyWidget: const ComLoading(), // example only
    loadingWidget: const ComEmpty(), // example only
    errorWidget: const ComErrorWidget(), // example only
    noNetworkWidget: (VoidCallback? onReconnect) => ComNoNetworkWidget(onReconnect: onReconnect), // example only
  ),
  child: child,
);

// BaseWidget states use global config by default; can be customized locally
BaseWidget(
  isConnected: isConnected,
  status: LayoutStatus.loading,
  loading: const ComLoading(),
  empty: const CustomEmpty(),
  error: BaseWidget.errorWidget(context),
  noNetwork: BaseWidget.noNetworkWidget(context),
  onReconnect: (){},
  child: child,
)

// State types
enum LayoutStatus {
  loading,
  success,
  empty,
  error,
  noNetwork,
}

// Global helpers
BaseWidget.loadingWidget(context)
BaseWidget.emptyWidget(context)
BaseWidget.errorWidget(context)
BaseWidget.noNetworkWidget(context)
...

Contributing

We welcome all contributions:

  • 🐛 Bug reports
  • 💡 Feature ideas
  • 📚 Docs improvements
  • 🎨 Design assets
  • 💻 Code contributions

License

MIT License – see LICENSE

카테고리

의존성

의존성 목록 4 개

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.