diff --git a/.github/workflows/PROJECT-FLUTTER-CI.yaml b/.github/workflows/PROJECT-FLUTTER-CI.yaml index 90fa68b..8754a21 100644 --- a/.github/workflows/PROJECT-FLUTTER-CI.yaml +++ b/.github/workflows/PROJECT-FLUTTER-CI.yaml @@ -473,6 +473,26 @@ jobs: echo "✅ Java setup completed" java -version + # Release Keystore 설정 (secrets가 있는 경우에만) + - name: Setup Release Keystore + if: ${{ secrets.RELEASE_KEYSTORE_BASE64 != '' }} + run: | + mkdir -p android/app/keystore + echo "${{ secrets.RELEASE_KEYSTORE_BASE64 }}" | base64 -d > android/app/keystore/key.jks + echo "✅ Release Keystore 생성 완료" + + # key.properties 생성 (secrets가 있는 경우에만) + - name: Create key.properties + if: ${{ secrets.RELEASE_KEYSTORE_BASE64 != '' }} + run: | + cat > android/key.properties << EOF + storeFile=app/keystore/key.jks + storePassword=${{ secrets.RELEASE_KEYSTORE_PASSWORD }} + keyAlias=${{ secrets.RELEASE_KEY_ALIAS }} + keyPassword=${{ secrets.RELEASE_KEY_PASSWORD }} + EOF + echo "✅ key.properties 생성 완료" + # Gradle 셋업 - name: Setup Gradle working-directory: android diff --git a/CHANGELOG.json b/CHANGELOG.json index 9361e08..ecec940 100644 --- a/CHANGELOG.json +++ b/CHANGELOG.json @@ -1,11 +1,34 @@ { "metadata": { - "lastUpdated": "2026-02-23T04:16:06Z", - "currentVersion": "1.0.42", + "lastUpdated": "2026-02-23T07:48:34Z", + "currentVersion": "1.0.45", "projectType": "flutter", - "totalReleases": 13 + "totalReleases": 14 }, "releases": [ + { + "version": "1.0.45", + "project_type": "flutter", + "date": "2026-02-23", + "pr_number": 45, + "raw_summary": "## Summary by CodeRabbit\n\n## v1.0.45 릴리스 노트\n\n* **새로운 기능**\n * AI 추출 버튼이 하단 네비게이션 바의 중앙에 통합되어 더 쉽게 접근할 수 있습니다.\n\n* **개선사항**\n * 버전 업데이트 (v1.0.45)\n * 빌드 프로세스 개선으로 더 안정적인 릴리스 배포가 가능해졌습니다.", + "parsed_changes": { + "새로운_기능": { + "title": "새로운 기능", + "items": [ + "AI 추출 버튼이 하단 네비게이션 바의 중앙에 통합되어 더 쉽게 접근할 수 있습니다." + ] + }, + "개선사항": { + "title": "개선사항", + "items": [ + "버전 업데이트 (v1.0.45)", + "빌드 프로세스 개선으로 더 안정적인 릴리스 배포가 가능해졌습니다." + ] + } + }, + "parse_method": "markdown" + }, { "version": "1.0.42", "project_type": "flutter", diff --git a/CHANGELOG.md b/CHANGELOG.md index db3d159..97a237e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,20 @@ # Changelog -**현재 버전:** 1.0.42 -**마지막 업데이트:** 2026-02-23T04:16:06Z +**현재 버전:** 1.0.45 +**마지막 업데이트:** 2026-02-23T07:48:34Z + +--- + +## [1.0.45] - 2026-02-23 + +**PR:** #45 + +**새로운 기능** +- AI 추출 버튼이 하단 네비게이션 바의 중앙에 통합되어 더 쉽게 접근할 수 있습니다. + +**개선사항** +- 버전 업데이트 (v1.0.45) +- 빌드 프로세스 개선으로 더 안정적인 릴리스 배포가 가능해졌습니다. --- diff --git a/README.md b/README.md index 354dfcc..b6c6ed9 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,6 @@ samples, guidance on mobile development, and a full API reference. --- -## 최신 버전 : v1.0.42 (2026-02-23) +## 최신 버전 : v1.0.43 (2026-02-23) [전체 버전 기록 보기](CHANGELOG.md) diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 143699c..10134bf 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -59,9 +59,12 @@ android { buildTypes { release { - signingConfig = signingConfigs.getByName("release") - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. + // key.properties가 있으면 release 서명, 없으면 debug 서명으로 fallback + signingConfig = if (keystorePropertiesFile.exists()) { + signingConfigs.getByName("release") + } else { + signingConfigs.getByName("debug") + } } } } diff --git a/lib/common/widgets/main_scaffold.dart b/lib/common/widgets/main_scaffold.dart index 4679781..6bef319 100644 --- a/lib/common/widgets/main_scaffold.dart +++ b/lib/common/widgets/main_scaffold.dart @@ -5,10 +5,10 @@ import 'package:go_router/go_router.dart'; import '../constants/home_colors.dart'; import '../../routing/route_paths.dart'; -/// 메인 네비게이션 셸 (하단 네비게이션 바 + FAB) +/// 메인 네비게이션 셸 (하단 네비게이션 바 + 중앙 AI 추출 버튼) /// /// StatefulShellRoute의 builder에서 사용되며, -/// 4탭(홈/검색/지도/마이) + 중앙 FAB(AI 추출) 구조를 제공합니다. +/// 4탭(홈/검색/지도/마이) + 중앙 버튼(AI 추출) 구조를 제공합니다. class MainScaffold extends StatelessWidget { const MainScaffold({ super.key, @@ -21,41 +21,29 @@ class MainScaffold extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( body: navigationShell, - floatingActionButton: SizedBox( - width: 56.w, - height: 56.w, - child: FloatingActionButton( - onPressed: () { - context.push(RoutePaths.aiExtraction); - }, - elevation: 2, - backgroundColor: HomeColors.textPrimary, - foregroundColor: HomeColors.background, - shape: const CircleBorder(), - child: Icon(Icons.add, size: 28.sp), - ), - ), - floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, bottomNavigationBar: _BottomNavBar( currentIndex: navigationShell.currentIndex, onTap: (index) => navigationShell.goBranch( index, initialLocation: index == navigationShell.currentIndex, ), + onAddTap: () => context.push(RoutePaths.aiExtraction), ), ); } } -/// 하단 네비게이션 바 (4탭 + 중앙 FAB 공간) +/// 하단 네비게이션 바 (4탭 + 중앙 AI 추출 버튼) class _BottomNavBar extends StatelessWidget { const _BottomNavBar({ required this.currentIndex, required this.onTap, + required this.onAddTap, }); final int currentIndex; final ValueChanged onTap; + final VoidCallback onAddTap; @override Widget build(BuildContext context) { @@ -86,7 +74,7 @@ class _BottomNavBar extends StatelessWidget { isSelected: currentIndex == 1, onTap: () => onTap(1), ), - SizedBox(width: 56.w), // FAB 공간 + _CenterAddButton(onTap: onAddTap), _NavItem( icon: Icons.map_outlined, activeIcon: Icons.map, @@ -109,6 +97,48 @@ class _BottomNavBar extends StatelessWidget { } } +/// 중앙 + 버튼 (AI 장소 추출 진입점) +class _CenterAddButton extends StatelessWidget { + const _CenterAddButton({ + required this.onTap, + }); + + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + behavior: HitTestBehavior.opaque, + child: SizedBox( + width: 64.w, + child: Center( + child: Container( + width: 48.w, + height: 48.w, + decoration: BoxDecoration( + color: HomeColors.textPrimary, + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: HomeColors.textPrimary.withValues(alpha: 0.2), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: Icon( + Icons.add, + size: 28.sp, + color: HomeColors.background, + ), + ), + ), + ), + ); + } +} + /// 네비게이션 아이템 (아이콘 + 라벨) class _NavItem extends StatelessWidget { const _NavItem({ diff --git a/pubspec.yaml b/pubspec.yaml index 527a680..b68bf0c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: mapsy description: "MapSy - Flutter Application" publish_to: "none" -version: 1.0.43+43 +version: 1.0.45+45 environment: sdk: ^3.9.2 dependencies: diff --git a/version.yml b/version.yml index 918a7d8..159c1ed 100644 --- a/version.yml +++ b/version.yml @@ -34,11 +34,11 @@ # - 버전은 항상 높은 버전으로 자동 동기화됩니다 # =================================================================== -version: "1.0.43" -version_code: 44 # app build number +version: "1.0.45" +version_code: 46 # app build number project_type: "flutter" # spring, flutter, react, react-native, react-native-expo, node, python, basic metadata: - last_updated: "2026-02-23 05:44:25" + last_updated: "2026-02-23 07:34:32" last_updated_by: "Cassiiopeia" default_branch: "main" integrated_from: "SUH-DEVOPS-TEMPLATE"