Frontend/Flutter

[Flutter] 플러터 오픈소스 라이선스 목록 만들기

김룹 2024. 5. 23. 17:03

 

 

flutter_oss_licenses | Dart package

A tool to generate detail and better OSS license list using pubspec.yaml/lock files.

pub.dev

 

 

1. flutter_oss_licenses 설치

 

👇 pubspec.yaml 에 추가

dev_dependencies:
  flutter_oss_licenses: ^3.0.2

 

공식홈페이지에 나와있는대로 3.0.2버전을 설치하려고 했으나 아래와 같은 에러 발생, 터미널에 나와있는대로 downgrade했다. 2.0.1로 진행함! 

 

 

👇 터미널창에 입력

flutter pub get
flutter pub run flutter_oss_licenses:generate.dart

 

🪸 두번째 명령어까지 입력하면 프로젝트 최상위에 oss_licenses.dart 파일 자동생성된다.

🪸 해당 파일 안에는 현재 프로젝트에 사용하고 있는 모든 패키지의 licenses 정보가 json 형태로 저장됨!

 

⚠️ 자동으로 생성된 oss_licenses.dart에는 모든 패키지가 다 저장되기 때문에, 명시할 패키지만 남겨두고 삭제하면 된다 

 

 

생성된 oss_licenses.dart 파일의 구조는 아래와 같다.

 

 

 

2. 페이지 생성

oss_licenses.dart에 있는 package들을 보여줄 page를 생성한다

 

👇 oss_licenses_page.dart

import 'package:flutter/material.dart';
import 'package:test/oss_licenses.dart';
import 'package:test/misc_oss_license_single.dart';

class OssLicensesPage extends StatelessWidget {
  const OssLicensesPage({super.key});

  static Future<List<String>> loadLicenses() async {
    final ossKeys = List<String>.from(ossLicenses);
    return ossKeys..sort();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('오픈소스 라이선스')),
      body: SingleChildScrollView(
        child: Column(
          children: [
            for (var i = 0; i < ossLicenses.length; i++)
              ListTile(
                title: Text(ossLicenses[i].name),
                subtitle: Text(ossLicenses[i].description),
                trailing: Icon(Icons.chevron_right),
                onTap: () {
                  Navigator.of(context).push(
                    MaterialPageRoute(
                      builder: (context) => MiscOssLicenseSingle(
                        name: ossLicenses[i].name,
                        version: ossLicenses[i].version,
                        description: ossLicenses[i].description,
                        licenseText: ossLicenses[i].license ?? '',
                        homepage: ossLicenses[i].homepage ?? '',
                      ),
                    ),
                  );
                },
              )
          ],
        ),
      ),
    );
  }
}

 

 

👇 misc_oss_license_single.dart

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

class MiscOssLicenseSingle extends StatelessWidget {
  final String name;
  final String version;
  final String description;
  final String licenseText;
  final String homepage;

  MiscOssLicenseSingle({
    super.key,
    required this.name,
    required this.version,
    required this.description,
    required this.licenseText,
    required this.homepage,
  });

  String _bodyText() {
    return licenseText.split('\n').map((line) {
      if (line.startsWith('//')) line = line.substring(2);
      line = line.trim();
      return line;
    }).join('\n');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          children: [
            ListTile(
              title: Text(name),
              subtitle: Text('version : $version'),
            ),
            Padding(
                padding:
                    const EdgeInsets.all(12),
                child: Text(description)),
            const Divider(),
            Padding(
              padding:
                  const EdgeInsets.all(12),
              child: Text(_bodyText()),
            ),
            const Divider(),
            ListTile(
              title: Text('Homepage'),
              subtitle: Text(homepage),
              onTap: () async {
                final Uri homepageUri = Uri.parse(homepage);
                if (await canLaunchUrl(homepageUri)) {
                  await launchUrl(homepageUri);
                } else {
                  throw '해당 페이지로 이동할 수 없습니다. $homepage';
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

 

 

3. 결과물

목록
누르면 위 상세 페이지로 이동!

 

 

현재 진행중인 프로젝트에서는 text나 color, header 등 style을 별도로 지정해서 사용했기 때문에 그대로 올릴 수 없어서 위에 올린 코드에는 복붙만해도 정상작동 되게끔 수정해서 올렸다. 그래서 업로드한 스크린샷과 디자인은 조금 다를 수 있음!