feat: Add Pro version lock mechanism for Lite version preparation

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 <noreply@anthropic.com>
This commit is contained in:
Ponshu Developer 2026-01-30 17:34:39 +09:00
parent 21833e4e75
commit f063ef6ec5
5 changed files with 198 additions and 5 deletions

View File

@ -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": []

View File

@ -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
///
/// truePro版
const bool isProVersion = bool.fromEnvironment('IS_PRO_VERSION', defaultValue: true);
void main() async {
WidgetsFlutterBinding.ensureInitialized();

View File

@ -794,4 +794,4 @@ class _ExposureSliderPainter extends CustomPainter {
oldDelegate.minValue != minValue ||
oldDelegate.maxValue != maxValue;
}
}
}

View File

@ -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<MainScreen> {
final t = Translations(userProfile.locale); // Translation helper
// Define Screens for each mode
// Pro版かLite版かで画面を切り替え
final List<Widget> 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

View File

@ -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.';
}
}
}