diff --git a/.github/workflows/web-deploy.yml b/.github/workflows/web-deploy.yml new file mode 100644 index 00000000..e096959a --- /dev/null +++ b/.github/workflows/web-deploy.yml @@ -0,0 +1,59 @@ +name: deploy flutter web to github pages + +on: + # main branch에 푸쉬가 들어올 경우 실행 + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + # git 기본 세팅 + - name: Checkout + uses: actions/checkout@v4 + + # 플러터 세팅 + - name: Setup flutter + uses: subosito/flutter-action@v2 + with: + channel: stable + flutter-version: 3.29.2 + + # 임의로 .env 파일 생성 + - name: Generate .env + run: | + cat < .env + SUPABASE_URL=${{ secrets.SUPABASE_URL }} + SUPABASE_ANON_KEY=${{ secrets.SUPABASE_ANON_KEY }} + EOF + + # 추가: 의존성 설치 + - name: Install dependencies + run: flutter pub get + + # Generator 빌드 + - name: Run Code Generation + run: flutter pub run build_runner build --delete-conflicting-outputs + + # Flutter Test 진행 + # => test에서 실패하면 배포가 되지 않도록 설정 + - name: Run Tests + run: flutter test + + # 플러터 웹 빌드 + - name: Build web + run: flutter build web --base-href "/${{ github.event.repository.name }}/" + + # 404.html = index.html 복사 + # => 강제 url로 라우팅이 404에러를 해결 + - name: Copy index.html to 404.html + run: cp build/web/index.html build/web/404.html + + # github page 배포 + - name: Deploy to github pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.WEB_DEPLOY_KEY }} + publish_dir: ./build/web \ No newline at end of file diff --git a/.gitignore b/.gitignore index dcfbce4e..81fb5a24 100644 --- a/.gitignore +++ b/.gitignore @@ -14,14 +14,14 @@ pubspec.lock package_config.json -# Flutter Web 관련 -/web/favicon.png -/web/icons/ -/web/splash/ -/web/manifest.json -/web/index.html -/web/flutter_service_worker.js -/web/assets/ +# Flutter Web 관련 ignore 설정 주석처리 +# /web/favicon.png +# /web/icons/ +# /web/splash/ +# /web/manifest.json +# /web/index.html +# /web/flutter_service_worker.js +# /web/assets/ # Android 관련 **/android/**/gradle-wrapper.jar @@ -156,4 +156,4 @@ logs/ devtools_options.yaml # Firebase -lib/firebase_options.dart +# lib/firebase_options.dart diff --git a/lib/auth/presentation/components/auth_header_widget.dart b/lib/auth/presentation/components/auth_header_widget.dart index bdee948b..8b51388d 100644 --- a/lib/auth/presentation/components/auth_header_widget.dart +++ b/lib/auth/presentation/components/auth_header_widget.dart @@ -20,7 +20,7 @@ class AuthHeaderWidget extends StatelessWidget { ), child: Center( child: Image.asset( - 'images/mongo_ai_logo.png', + 'assets/images/mongo_ai_logo.png', width: 24, height: 24, ), diff --git a/lib/auth/presentation/sign_in/screen/sign_in_screen.dart b/lib/auth/presentation/sign_in/screen/sign_in_screen.dart index f9e045f0..4c300e4f 100644 --- a/lib/auth/presentation/sign_in/screen/sign_in_screen.dart +++ b/lib/auth/presentation/sign_in/screen/sign_in_screen.dart @@ -141,7 +141,9 @@ class _SignInScreenState extends State { ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: AppColor.primary), + borderSide: const BorderSide( + color: AppColor.primary, + ), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), @@ -204,7 +206,9 @@ class _SignInScreenState extends State { ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), - borderSide: const BorderSide(color: AppColor.primary), + borderSide: const BorderSide( + color: AppColor.primary, + ), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), @@ -287,7 +291,9 @@ class _SignInScreenState extends State { ElevatedButton( onPressed: () { - widget.onAction(const SignInAction.onTapGoogleSingIn()); + widget.onAction( + const SignInAction.onTapGoogleSingIn(), + ); }, style: ElevatedButton.styleFrom( backgroundColor: AppColor.white, @@ -300,11 +306,28 @@ class _SignInScreenState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: SizedBox(width: 40, height: 40, child: Image.asset('images/google_logo.png', width: 40, height: 40,)), + padding: const EdgeInsets.symmetric( + vertical: 10, + ), + child: SizedBox( + width: 40, + height: 40, + child: Image.asset( + 'assets/images/google_logo.png', + width: 40, + height: 40, + ), + ), ), const Gap(10), - Text('Sign in with Google', style: AppTextStyle.bodyMedium.copyWith(fontWeight: FontWeight.w500, color: AppColor.black, fontSize: 16)) + Text( + 'Sign in with Google', + style: AppTextStyle.bodyMedium.copyWith( + fontWeight: FontWeight.w500, + color: AppColor.black, + fontSize: 16, + ), + ), ], ), ), @@ -325,7 +348,9 @@ class _SignInScreenState extends State { ), GestureDetector( onTap: - () => widget.onAction(const SignInAction.onTapSignUp()), + () => widget.onAction( + const SignInAction.onTapSignUp(), + ), child: Text( '회원가입', style: AppTextStyle.captionRegular.copyWith( diff --git a/lib/dashboard/presentation/dashboard_screen.dart b/lib/dashboard/presentation/dashboard_screen.dart index f72c824f..4457ea0d 100644 --- a/lib/dashboard/presentation/dashboard_screen.dart +++ b/lib/dashboard/presentation/dashboard_screen.dart @@ -36,7 +36,9 @@ class _DashboardScreenState extends ConsumerState { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { - unawaited(ref.read(dashboardViewModelProvider.notifier).fetchSelectedTeam()); + unawaited( + ref.read(dashboardViewModelProvider.notifier).fetchSelectedTeam(), + ); }); } @@ -51,7 +53,7 @@ class _DashboardScreenState extends ConsumerState { _currentPath = ['최근 항목']; } else if (selectedIndex == 3) { _currentPath = ['휴지통']; - } else if(selectedIndex == 4) { + } else if (selectedIndex == 4) { _currentPath = ['내 정보']; } @@ -74,35 +76,35 @@ class _DashboardScreenState extends ConsumerState { children: [ PathWidget(path: _currentPath), const Spacer(), - ElevatedButton( - onPressed: () { - context.go(Routes.myProfile); - }, - style: ElevatedButton.styleFrom( - backgroundColor: AppColor.white, - shadowColor: Colors.transparent, - overlayColor: Colors.transparent, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(0), - ), - ), - child: Row( - children: [ - const Icon( - Icons.person, - color: AppColor.deepBlack, - ), - const Gap(10), - Text( - dashboard.userProfile.userName, - style: AppTextStyle.bodyMedium.copyWith( - fontWeight: FontWeight.bold, - color: AppColor.black + ElevatedButton( + onPressed: () { + context.go(Routes.myProfile); + }, + style: ElevatedButton.styleFrom( + backgroundColor: AppColor.white, + shadowColor: Colors.transparent, + overlayColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), ), ), - ], - ), - ), + child: Row( + children: [ + const Icon( + Icons.person, + color: AppColor.deepBlack, + ), + const Gap(10), + Text( + dashboard.userProfile.userName, + style: AppTextStyle.bodyMedium.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.black, + ), + ), + ], + ), + ), ], ), ), @@ -166,7 +168,7 @@ class _DashboardScreenState extends ConsumerState { height: 40, child: SelectModeButtonWidget( onClick: () { - if(dashboard.currentTeamId != null) { + if (dashboard.currentTeamId != null) { viewModel.toggleSelectMode(); } }, @@ -235,7 +237,7 @@ class _DashboardScreenState extends ConsumerState { ), child: Center( child: Image.asset( - 'images/mongo_ai_logo.png', + 'assets/images/mongo_ai_logo.png', width: 16, height: 16, ), diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart new file mode 100644 index 00000000..a13c01b1 --- /dev/null +++ b/lib/firebase_options.dart @@ -0,0 +1,64 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: type=lint +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + return web; + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for android - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.iOS: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for ios - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.macOS: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for macos - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.windows: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for windows - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions web = FirebaseOptions( + apiKey: 'AIzaSyDv6taLhWiRmfLBY7v7h2iZRHABowiB4UU', + appId: '1:108515543625:web:3a816c4fb36a9baaa74d98', + messagingSenderId: '108515543625', + projectId: 'mongo-ai-9d6ac', + authDomain: 'mongo-ai-9d6ac.firebaseapp.com', + storageBucket: 'mongo-ai-9d6ac.firebasestorage.app', + measurementId: 'G-ZB5G231MQH', + ); +} diff --git a/pubspec.yaml b/pubspec.yaml index 019f8d4a..a5504c18 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -105,6 +105,7 @@ flutter: uses-material-design: true assets: - .env + - assets/images/ fonts: - family: Pretendard diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 00000000..015a7e78 Binary files /dev/null and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 00000000..b749bfef Binary files /dev/null and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 00000000..88cfd48d Binary files /dev/null and b/web/icons/Icon-512.png differ diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png new file mode 100644 index 00000000..eb9b4d76 Binary files /dev/null and b/web/icons/Icon-maskable-192.png differ diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png new file mode 100644 index 00000000..d69c5669 Binary files /dev/null and b/web/icons/Icon-maskable-512.png differ diff --git a/web/index.html b/web/index.html new file mode 100644 index 00000000..e028b067 --- /dev/null +++ b/web/index.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + mongoai_web + + + + + + diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 00000000..9e8063f4 --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "mongoai_web", + "short_name": "mongoai_web", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +}