From f063ef6ec582e0efda318306757fc8a7081f11e2 Mon Sep 17 00:00:00 2001 From: Ponshu Developer Date: Fri, 30 Jan 2026 17:34:39 +0900 Subject: [PATCH] feat: Add Pro version lock mechanism for Lite version preparation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 4.1完了: Pro版機能ロック機構の実装 変更内容: - lib/widgets/pro_locked_screen.dart: 新規作成 - 和モダンな王冠アイコン付きロック画面 - Pro版限定機能を分かりやすく表示 - 日英両対応 - lib/main.dart: IS_PRO_VERSION ビルドフラグ追加 - bool.fromEnvironment('IS_PRO_VERSION', defaultValue: true) - Pro版/Lite版をビルド時に切り替え可能に - lib/screens/main_screen.dart: 条件分岐ロジック追加 - パーソナルモード: QRスキャン → Lite版ではロック画面 - ビジネスモード: Instagram・分析 → Lite版ではロック画面 - タブ表示は維持、タップ時にロック画面を表示 ビルドコマンド: - Pro版: flutter build apk --release --dart-define=IS_PRO_VERSION=true - Lite版: flutter build apk --release --dart-define=IS_PRO_VERSION=false 次ステップ: - lite-versionブランチ作成 - QR依存関係削除(pubspec.yaml) - パッケージ名・アプリ名変更 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .claude/settings.local.json | 4 +- lib/main.dart | 9 ++ lib/screens/camera_screen.dart | 2 +- lib/screens/main_screen.dart | 36 ++++++- lib/widgets/pro_locked_screen.dart | 152 +++++++++++++++++++++++++++++ 5 files changed, 198 insertions(+), 5 deletions(-) create mode 100644 lib/widgets/pro_locked_screen.dart diff --git a/.claude/settings.local.json b/.claude/settings.local.json index c0cf657..05151ad 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -49,7 +49,9 @@ "Bash(git checkout:*)", "Bash(Select-Object -Last 10)", "Bash(Select-Object -Last 30)", - "Bash(Select-String \"app_theme\")" + "Bash(Select-String \"app_theme\")", + "Bash(git tag:*)", + "Bash(Select-Object -Last 20)" ], "deny": [], "ask": [] diff --git a/lib/main.dart b/lib/main.dart index 41a9ffc..5efd560 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,6 +9,15 @@ import 'providers/theme_provider.dart'; import 'screens/main_screen.dart'; import 'services/migration_service.dart'; +/// Pro版かLite版かを判定するビルド時フラグ +/// +/// ビルドコマンド: +/// - Pro版: flutter build apk --release --dart-define=IS_PRO_VERSION=true +/// - Lite版: flutter build apk --release --dart-define=IS_PRO_VERSION=false +/// +/// デフォルトはtrue(Pro版) +const bool isProVersion = bool.fromEnvironment('IS_PRO_VERSION', defaultValue: true); + void main() async { WidgetsFlutterBinding.ensureInitialized(); diff --git a/lib/screens/camera_screen.dart b/lib/screens/camera_screen.dart index abbdda0..f24b142 100644 --- a/lib/screens/camera_screen.dart +++ b/lib/screens/camera_screen.dart @@ -794,4 +794,4 @@ class _ExposureSliderPainter extends CustomPainter { oldDelegate.minValue != minValue || oldDelegate.maxValue != maxValue; } -} +} \ No newline at end of file diff --git a/lib/screens/main_screen.dart b/lib/screens/main_screen.dart index a2d5cdb..b2f4620 100644 --- a/lib/screens/main_screen.dart +++ b/lib/screens/main_screen.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:lucide_icons/lucide_icons.dart'; +import '../main.dart'; // Import isProVersion flag import '../providers/theme_provider.dart'; // Access userProfileProvider import '../providers/navigation_provider.dart'; // Track current tab index import '../utils/translations.dart'; // Translation helper +import '../widgets/pro_locked_screen.dart'; // Pro版ロック画面 import 'home_screen.dart'; import 'soul_screen.dart'; import 'shop_settings_screen.dart'; @@ -45,16 +47,44 @@ class _MainScreenState extends ConsumerState { final t = Translations(userProfile.locale); // Translation helper // Define Screens for each mode + // Pro版かLite版かで画面を切り替え final List screens = isBusiness ? [ const HomeScreen(), // Inventory Management (FAB opens Menu Creation) - const InstaSupportScreen(), // Social Media Support - const AnalyticsScreen(), // Analytics + // Instagram Support: Pro版のみ + isProVersion + ? const InstaSupportScreen() + : ProLockedScreen( + featureName: t['promo'], + featureIcon: LucideIcons.instagram, + description: userProfile.locale == 'ja' + ? 'Instagram用の魅力的な投稿を自動生成。\n酒の写真とAI解析を活用して、\nプロモーションをサポートします。' + : 'Auto-generate attractive Instagram posts.\nLeverage sake photos and AI analysis\nto boost your promotion.', + ), + // Analytics: Pro版のみ + isProVersion + ? const AnalyticsScreen() + : ProLockedScreen( + featureName: t['analytics'], + featureIcon: LucideIcons.barChart, + description: userProfile.locale == 'ja' + ? '在庫状況や人気銘柄を分析。\nビジネスの意思決定を\nデータで支援します。' + : 'Analyze inventory and popular brands.\nSupport business decisions\nwith data insights.', + ), const ShopSettingsScreen(), // Shop Settings ] : [ const HomeScreen(), // My Sake List - const ScanARScreen(), + // QR Scan: Pro版のみ + isProVersion + ? const ScanARScreen() + : ProLockedScreen( + featureName: t['scan'], + featureIcon: LucideIcons.scanLine, + description: userProfile.locale == 'ja' + ? 'QRコードをスキャンして、\n酒の情報を素早く登録。\nAR表示で楽しく記録できます。' + : 'Scan QR codes to quickly register\nsake information.\nEnjoy recording with AR display.', + ), const SommelierScreen(), const BreweryMapScreen(), const SoulScreen(), // MyPage/Settings diff --git a/lib/widgets/pro_locked_screen.dart b/lib/widgets/pro_locked_screen.dart new file mode 100644 index 0000000..f59c1db --- /dev/null +++ b/lib/widgets/pro_locked_screen.dart @@ -0,0 +1,152 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:lucide_icons/lucide_icons.dart'; +import '../providers/theme_provider.dart'; + +/// Pro版限定機能のロック画面 +/// +/// Lite版で使用制限されている機能を表示する際に使用。 +/// 和モダンなデザインで、王冠アイコンと共に「Pro版限定」であることを伝える。 +class ProLockedScreen extends ConsumerWidget { + final String featureName; + final IconData featureIcon; + final String? description; + + const ProLockedScreen({ + super.key, + required this.featureName, + required this.featureIcon, + this.description, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final userProfile = ref.watch(userProfileProvider); + final appColors = Theme.of(context).colorScheme; + + // デフォルトの説明文を生成 + final String displayDescription = description ?? _getDefaultDescription(featureName, userProfile.locale); + + return Scaffold( + appBar: AppBar( + title: Text(featureName), + backgroundColor: Colors.transparent, + elevation: 0, + ), + body: Center( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // 機能アイコン(グレーアウト) + Icon( + featureIcon, + size: 64, + color: appColors.onSurface.withValues(alpha: 0.3), + ), + const SizedBox(height: 24), + + // 王冠アイコン(和モダンな細いライン) + Icon( + LucideIcons.crown, + size: 48, + color: appColors.primary.withValues(alpha: 0.7), + ), + const SizedBox(height: 16), + + // Pro版限定メッセージ + Text( + userProfile.locale == 'ja' + ? 'Pro版限定機能' + : 'Pro Version Only', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w600, + color: appColors.onSurface, + ), + ), + const SizedBox(height: 8), + + // 機能名 + Text( + featureName, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: appColors.primary, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 24), + + // 説明文 + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: appColors.primary.withValues(alpha: 0.05), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: appColors.primary.withValues(alpha: 0.2), + width: 1, + ), + ), + child: Text( + displayDescription, + style: TextStyle( + fontSize: 14, + height: 1.6, + color: appColors.onSurface.withValues(alpha: 0.8), + ), + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 32), + + // Pro版へのアップグレード案内(将来実装用) + TextButton.icon( + onPressed: () { + // TODO: Pro版購入画面への遷移(Phase 2で実装) + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + userProfile.locale == 'ja' + ? 'Pro版は近日公開予定です' + : 'Pro version coming soon', + ), + duration: const Duration(seconds: 2), + ), + ); + }, + icon: const Icon(LucideIcons.sparkles, size: 18), + label: Text( + userProfile.locale == 'ja' + ? 'Pro版について' + : 'About Pro Version', + style: const TextStyle(fontSize: 16), + ), + style: TextButton.styleFrom( + foregroundColor: appColors.primary, + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + ), + ), + ], + ), + ), + ), + ); + } + + /// 機能名に応じたデフォルト説明文を生成 + String _getDefaultDescription(String featureName, String locale) { + if (locale == 'ja') { + return 'この機能はPonshu Room Pro版でご利用いただけます。\n' + 'Pro版では、より充実した酒ライフをサポートする\n' + '多彩な機能をお楽しみいただけます。'; + } else { + return 'This feature is available in Ponshu Room Pro.\n' + 'Enjoy enhanced sake experience with\n' + 'a wide range of premium features.'; + } + } +}