feat(divination): 重构手动起卦教程,支持三硬币交互选择
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 222 KiB |
|
Before Width: | Height: | Size: 336 KiB |
|
Before Width: | Height: | Size: 409 KiB |
|
Before Width: | Height: | Size: 331 KiB |
|
Before Width: | Height: | Size: 344 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 799 KiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 3.0 MiB |
@@ -77,7 +77,6 @@ class DivinationApi {
|
|||||||
final aggregate = DivinationRunAggregate(
|
final aggregate = DivinationRunAggregate(
|
||||||
derived: derived,
|
derived: derived,
|
||||||
signLevel: _asString(agentOutputRaw['sign_level']),
|
signLevel: _asString(agentOutputRaw['sign_level']),
|
||||||
summary: _asString(agentOutputRaw['summary']),
|
|
||||||
conclusion: _asStringList(agentOutputRaw['conclusion']),
|
conclusion: _asStringList(agentOutputRaw['conclusion']),
|
||||||
focusPoints: _asStringList(agentOutputRaw['focus_points']),
|
focusPoints: _asStringList(agentOutputRaw['focus_points']),
|
||||||
advice: _asStringList(agentOutputRaw['advice']),
|
advice: _asStringList(agentOutputRaw['advice']),
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ class DivinationRunAggregate {
|
|||||||
const DivinationRunAggregate({
|
const DivinationRunAggregate({
|
||||||
required this.derived,
|
required this.derived,
|
||||||
required this.signLevel,
|
required this.signLevel,
|
||||||
required this.summary,
|
|
||||||
required this.conclusion,
|
required this.conclusion,
|
||||||
required this.focusPoints,
|
required this.focusPoints,
|
||||||
required this.advice,
|
required this.advice,
|
||||||
@@ -64,7 +63,6 @@ class DivinationRunAggregate {
|
|||||||
|
|
||||||
final DerivedDivinationData derived;
|
final DerivedDivinationData derived;
|
||||||
final String signLevel;
|
final String signLevel;
|
||||||
final String summary;
|
|
||||||
final List<String> conclusion;
|
final List<String> conclusion;
|
||||||
final List<String> focusPoints;
|
final List<String> focusPoints;
|
||||||
final List<String> advice;
|
final List<String> advice;
|
||||||
@@ -82,8 +80,9 @@ class DivinationRunAggregate {
|
|||||||
lowerName: derived.lowerName,
|
lowerName: derived.lowerName,
|
||||||
signType: signLevel,
|
signType: signLevel,
|
||||||
keywords: keywords.join('、'),
|
keywords: keywords.join('、'),
|
||||||
|
focusPoints: focusPoints,
|
||||||
conclusion: _asBullet(conclusion),
|
conclusion: _asBullet(conclusion),
|
||||||
analysis: summary.isEmpty ? answer : '$summary\n\n$answer',
|
analysis: answer,
|
||||||
suggestion: _asBullet(advice),
|
suggestion: _asBullet(advice),
|
||||||
ganzhi: GanzhiData(
|
ganzhi: GanzhiData(
|
||||||
yearGanZhi: derived.ganzhi.yearGanZhi,
|
yearGanZhi: derived.ganzhi.yearGanZhi,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class DivinationParams {
|
|||||||
required this.divinationTime,
|
required this.divinationTime,
|
||||||
required this.coinBalance,
|
required this.coinBalance,
|
||||||
required this.userId,
|
required this.userId,
|
||||||
|
this.allowVibration = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
final DivinationMethod method;
|
final DivinationMethod method;
|
||||||
@@ -30,6 +31,7 @@ class DivinationParams {
|
|||||||
final DateTime divinationTime;
|
final DateTime divinationTime;
|
||||||
final int coinBalance;
|
final int coinBalance;
|
||||||
final String userId;
|
final String userId;
|
||||||
|
final bool allowVibration;
|
||||||
|
|
||||||
DivinationParams copyWith({
|
DivinationParams copyWith({
|
||||||
DivinationMethod? method,
|
DivinationMethod? method,
|
||||||
@@ -38,6 +40,7 @@ class DivinationParams {
|
|||||||
DateTime? divinationTime,
|
DateTime? divinationTime,
|
||||||
int? coinBalance,
|
int? coinBalance,
|
||||||
String? userId,
|
String? userId,
|
||||||
|
bool? allowVibration,
|
||||||
}) {
|
}) {
|
||||||
return DivinationParams(
|
return DivinationParams(
|
||||||
method: method ?? this.method,
|
method: method ?? this.method,
|
||||||
@@ -46,6 +49,7 @@ class DivinationParams {
|
|||||||
divinationTime: divinationTime ?? this.divinationTime,
|
divinationTime: divinationTime ?? this.divinationTime,
|
||||||
coinBalance: coinBalance ?? this.coinBalance,
|
coinBalance: coinBalance ?? this.coinBalance,
|
||||||
userId: userId ?? this.userId,
|
userId: userId ?? this.userId,
|
||||||
|
allowVibration: allowVibration ?? this.allowVibration,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class DivinationResultData {
|
|||||||
required this.lowerName,
|
required this.lowerName,
|
||||||
required this.signType,
|
required this.signType,
|
||||||
required this.keywords,
|
required this.keywords,
|
||||||
|
required this.focusPoints,
|
||||||
required this.conclusion,
|
required this.conclusion,
|
||||||
required this.analysis,
|
required this.analysis,
|
||||||
required this.suggestion,
|
required this.suggestion,
|
||||||
@@ -29,6 +30,7 @@ class DivinationResultData {
|
|||||||
final String lowerName;
|
final String lowerName;
|
||||||
final String signType;
|
final String signType;
|
||||||
final String keywords;
|
final String keywords;
|
||||||
|
final List<String> focusPoints;
|
||||||
final String conclusion;
|
final String conclusion;
|
||||||
final String analysis;
|
final String analysis;
|
||||||
final String suggestion;
|
final String suggestion;
|
||||||
@@ -50,6 +52,7 @@ class DivinationResultData {
|
|||||||
'lowerName': lowerName,
|
'lowerName': lowerName,
|
||||||
'signType': signType,
|
'signType': signType,
|
||||||
'keywords': keywords,
|
'keywords': keywords,
|
||||||
|
'focusPoints': focusPoints,
|
||||||
'conclusion': conclusion,
|
'conclusion': conclusion,
|
||||||
'analysis': analysis,
|
'analysis': analysis,
|
||||||
'suggestion': suggestion,
|
'suggestion': suggestion,
|
||||||
@@ -86,6 +89,7 @@ class DivinationResultData {
|
|||||||
lowerName: _requiredString(json, 'lowerName'),
|
lowerName: _requiredString(json, 'lowerName'),
|
||||||
signType: _requiredString(json, 'signType'),
|
signType: _requiredString(json, 'signType'),
|
||||||
keywords: _requiredString(json, 'keywords'),
|
keywords: _requiredString(json, 'keywords'),
|
||||||
|
focusPoints: _requiredStringList(json, 'focusPoints'),
|
||||||
conclusion: _requiredString(json, 'conclusion'),
|
conclusion: _requiredString(json, 'conclusion'),
|
||||||
analysis: _requiredString(json, 'analysis'),
|
analysis: _requiredString(json, 'analysis'),
|
||||||
suggestion: _requiredString(json, 'suggestion'),
|
suggestion: _requiredString(json, 'suggestion'),
|
||||||
@@ -113,6 +117,21 @@ class DivinationResultData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> _requiredStringList(Map<String, dynamic> json, String key) {
|
||||||
|
final raw = json[key];
|
||||||
|
if (raw is! List<dynamic>) {
|
||||||
|
throw FormatException('Invalid $key payload');
|
||||||
|
}
|
||||||
|
return raw
|
||||||
|
.map((item) {
|
||||||
|
if (item is! String) {
|
||||||
|
throw FormatException('Invalid $key item payload');
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
})
|
||||||
|
.toList(growable: false);
|
||||||
|
}
|
||||||
|
|
||||||
class GanzhiData {
|
class GanzhiData {
|
||||||
const GanzhiData({
|
const GanzhiData({
|
||||||
required this.yearGanZhi,
|
required this.yearGanZhi,
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class DivinationRunService {
|
|||||||
|
|
||||||
DerivedDivinationData? derived;
|
DerivedDivinationData? derived;
|
||||||
String signLevel = '';
|
String signLevel = '';
|
||||||
String summary = '';
|
|
||||||
List<String> conclusion = const <String>[];
|
List<String> conclusion = const <String>[];
|
||||||
List<String> focusPoints = const <String>[];
|
List<String> focusPoints = const <String>[];
|
||||||
List<String> advice = const <String>[];
|
List<String> advice = const <String>[];
|
||||||
@@ -64,7 +63,6 @@ class DivinationRunService {
|
|||||||
}
|
}
|
||||||
if (type == 'TEXT_MESSAGE_END') {
|
if (type == 'TEXT_MESSAGE_END') {
|
||||||
signLevel = _requiredString(event, 'sign_level');
|
signLevel = _requiredString(event, 'sign_level');
|
||||||
summary = _requiredString(event, 'summary');
|
|
||||||
conclusion = _requiredStringList(event, 'conclusion');
|
conclusion = _requiredStringList(event, 'conclusion');
|
||||||
focusPoints = _requiredStringList(event, 'focus_points');
|
focusPoints = _requiredStringList(event, 'focus_points');
|
||||||
advice = _requiredStringList(event, 'advice');
|
advice = _requiredStringList(event, 'advice');
|
||||||
@@ -107,7 +105,6 @@ class DivinationRunService {
|
|||||||
return DivinationRunAggregate(
|
return DivinationRunAggregate(
|
||||||
derived: derived,
|
derived: derived,
|
||||||
signLevel: signLevel,
|
signLevel: signLevel,
|
||||||
summary: summary,
|
|
||||||
conclusion: conclusion,
|
conclusion: conclusion,
|
||||||
focusPoints: focusPoints,
|
focusPoints: focusPoints,
|
||||||
advice: advice,
|
advice: advice,
|
||||||
|
|||||||
@@ -300,6 +300,9 @@ class _AutoDivinationScreenState extends State<AutoDivinationScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _vibrateStrong() async {
|
Future<void> _vibrateStrong() async {
|
||||||
|
if (!widget.params.allowVibration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final hasVibrator = await Vibration.hasVibrator();
|
final hasVibrator = await Vibration.hasVibrator();
|
||||||
if (hasVibrator == true) {
|
if (hasVibrator == true) {
|
||||||
await Vibration.vibrate(duration: 280, amplitude: 255);
|
await Vibration.vibrate(duration: 280, amplitude: 255);
|
||||||
@@ -313,15 +316,17 @@ class _AutoDivinationScreenState extends State<AutoDivinationScreen>
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return DivinationGuideDialog(
|
return DivinationGuideDialog(
|
||||||
title: l10n.autoGuideTitle,
|
title: l10n.divinationManualGuideTitle,
|
||||||
guideImages: const [
|
guideImages: const [
|
||||||
'assets/images/qigua/lc1.jpg',
|
['assets/images/tutorial/tutorial_1.png'],
|
||||||
'assets/images/qigua/lc2.jpg',
|
['assets/images/tutorial/tutorial_2.png'],
|
||||||
'assets/images/qigua/lc3.jpg',
|
['assets/images/tutorial/tutorial_3.png'],
|
||||||
'assets/images/qigua/lc4.jpg',
|
],
|
||||||
'assets/images/qigua/lc5.jpg',
|
instructions: [
|
||||||
|
l10n.divinationManualGuideStep1,
|
||||||
|
l10n.divinationManualGuideStep2,
|
||||||
|
l10n.divinationManualGuideStep3,
|
||||||
],
|
],
|
||||||
instructionText: l10n.autoGuideInstruction,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -527,7 +532,7 @@ class _CoinColumn extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: AppSpacing.sm),
|
const SizedBox(height: AppSpacing.sm),
|
||||||
Text(
|
Text(
|
||||||
DivinationTerms.yinYang[isYang] ?? '',
|
DivinationTerms.ziHua[isYang] ?? '',
|
||||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
color: colors.onSurface,
|
color: colors.onSurface,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
@@ -562,8 +567,8 @@ class _CoinFace extends StatelessWidget {
|
|||||||
: (isYang ? 0 : 180);
|
: (isYang ? 0 : 180);
|
||||||
final showingYang = isSpinning ? rotationY < 90 : isYang;
|
final showingYang = isSpinning ? rotationY < 90 : isYang;
|
||||||
final image = showingYang
|
final image = showingYang
|
||||||
? 'assets/images/qigua/yangmian.jpg'
|
? 'assets/images/qigua/hua.jpg'
|
||||||
: 'assets/images/qigua/yinmian.jpg';
|
: 'assets/images/qigua/zi.jpg';
|
||||||
return Transform(
|
return Transform(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
transform: Matrix4.identity()
|
transform: Matrix4.identity()
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ class _DivinationProcessingScreenState extends State<DivinationProcessingScreen>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'I Ching',
|
l10n.iChingTitle,
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.labelSmall
|
.labelSmall
|
||||||
|
|||||||
@@ -175,6 +175,8 @@ class _DivinationResultScreenState extends State<DivinationResultScreen> {
|
|||||||
content: widget.data.conclusion,
|
content: widget.data.conclusion,
|
||||||
),
|
),
|
||||||
const SizedBox(height: AppSpacing.md),
|
const SizedBox(height: AppSpacing.md),
|
||||||
|
_FocusPointsCard(points: widget.data.focusPoints),
|
||||||
|
const SizedBox(height: AppSpacing.md),
|
||||||
_AnalysisCard(
|
_AnalysisCard(
|
||||||
title: l10n.resultAnalysis,
|
title: l10n.resultAnalysis,
|
||||||
content: widget.data.analysis,
|
content: widget.data.analysis,
|
||||||
@@ -426,6 +428,71 @@ class _KeywordCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _FocusPointsCard extends StatelessWidget {
|
||||||
|
const _FocusPointsCard({required this.points});
|
||||||
|
|
||||||
|
final List<String> points;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final colors = Theme.of(context).colorScheme;
|
||||||
|
final languageCode = Localizations.localeOf(context).languageCode;
|
||||||
|
final title = languageCode == 'en' ? 'Focus Points' : '断卦要点';
|
||||||
|
if (points.isEmpty) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
return Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
color: colors.surface,
|
||||||
|
elevation: 2,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(AppSpacing.lg),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
|
color: colors.primary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: AppSpacing.sm),
|
||||||
|
...List<Widget>.generate(points.length, (index) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: AppSpacing.xs),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'${index + 1}. ',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
color: colors.primary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
points[index],
|
||||||
|
style: Theme.of(
|
||||||
|
context,
|
||||||
|
).textTheme.bodyMedium?.copyWith(height: 1.55),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _AnalysisCard extends StatelessWidget {
|
class _AnalysisCard extends StatelessWidget {
|
||||||
const _AnalysisCard({required this.title, required this.content});
|
const _AnalysisCard({required this.title, required this.content});
|
||||||
|
|
||||||
@@ -715,8 +782,11 @@ class _HexagramDetailCard extends StatelessWidget {
|
|||||||
for (int idx = 5; idx >= 0; idx--)
|
for (int idx = 5; idx >= 0; idx--)
|
||||||
_YaoDetailRow(
|
_YaoDetailRow(
|
||||||
line: data.yaoLines[idx],
|
line: data.yaoLines[idx],
|
||||||
target: data.targetYaoLines[idx],
|
target: idx < data.targetYaoLines.length
|
||||||
showTarget: data.hasChangingYao,
|
? data.targetYaoLines[idx]
|
||||||
|
: data.yaoLines[idx],
|
||||||
|
showTarget:
|
||||||
|
data.hasChangingYao && idx < data.targetYaoLines.length,
|
||||||
),
|
),
|
||||||
const SizedBox(height: AppSpacing.sm),
|
const SizedBox(height: AppSpacing.sm),
|
||||||
const Align(
|
const Align(
|
||||||
|
|||||||
@@ -24,12 +24,14 @@ class DivinationScreen extends StatefulWidget {
|
|||||||
required this.userId,
|
required this.userId,
|
||||||
required this.onCompleted,
|
required this.onCompleted,
|
||||||
this.runServiceOverride,
|
this.runServiceOverride,
|
||||||
|
this.allowVibration = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
final SessionStore sessionStore;
|
final SessionStore sessionStore;
|
||||||
final String userId;
|
final String userId;
|
||||||
final Future<void> Function(DivinationResultData result) onCompleted;
|
final Future<void> Function(DivinationResultData result) onCompleted;
|
||||||
final DivinationRunService? runServiceOverride;
|
final DivinationRunService? runServiceOverride;
|
||||||
|
final bool allowVibration;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DivinationScreen> createState() => _DivinationScreenState();
|
State<DivinationScreen> createState() => _DivinationScreenState();
|
||||||
@@ -51,7 +53,7 @@ class _DivinationScreenState extends State<DivinationScreen> {
|
|||||||
widget.runServiceOverride ??
|
widget.runServiceOverride ??
|
||||||
DivinationRunService(api: DivinationApi(apiClient: apiClient));
|
DivinationRunService(api: DivinationApi(apiClient: apiClient));
|
||||||
_params = DivinationParams(
|
_params = DivinationParams(
|
||||||
method: DivinationMethod.manual,
|
method: DivinationMethod.auto,
|
||||||
questionType: QuestionType.career,
|
questionType: QuestionType.career,
|
||||||
question: '',
|
question: '',
|
||||||
divinationTime: DateTime.now(),
|
divinationTime: DateTime.now(),
|
||||||
@@ -169,7 +171,10 @@ class _DivinationScreenState extends State<DivinationScreen> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final nextParams = _params.copyWith(divinationTime: DateTime.now());
|
final nextParams = _params.copyWith(
|
||||||
|
divinationTime: DateTime.now(),
|
||||||
|
allowVibration: widget.allowVibration,
|
||||||
|
);
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute<void>(
|
MaterialPageRoute<void>(
|
||||||
builder: (_) => AutoDivinationScreen(
|
builder: (_) => AutoDivinationScreen(
|
||||||
@@ -406,13 +411,15 @@ Future<void> _showGuide(BuildContext context, AppLocalizations l10n) {
|
|||||||
return DivinationGuideDialog(
|
return DivinationGuideDialog(
|
||||||
title: l10n.divinationManualGuideTitle,
|
title: l10n.divinationManualGuideTitle,
|
||||||
guideImages: const [
|
guideImages: const [
|
||||||
'assets/images/qigua/lc1.jpg',
|
['assets/images/tutorial/tutorial_1.png'],
|
||||||
'assets/images/qigua/lc2.jpg',
|
['assets/images/tutorial/tutorial_2.png'],
|
||||||
'assets/images/qigua/lc3.jpg',
|
['assets/images/tutorial/tutorial_3.png'],
|
||||||
'assets/images/qigua/lc4.jpg',
|
],
|
||||||
'assets/images/qigua/lc5.jpg',
|
instructions: [
|
||||||
|
l10n.divinationManualGuideStep1,
|
||||||
|
l10n.divinationManualGuideStep2,
|
||||||
|
l10n.divinationManualGuideStep3,
|
||||||
],
|
],
|
||||||
instructionText: l10n.divinationManualGuideInstruction,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
@@ -130,8 +132,16 @@ class _ManualDivinationScreenState extends State<ManualDivinationScreen>
|
|||||||
builder: (_) {
|
builder: (_) {
|
||||||
return DivinationGuideDialog(
|
return DivinationGuideDialog(
|
||||||
title: l10n.manualSelectYaoTitle,
|
title: l10n.manualSelectYaoTitle,
|
||||||
guideImages: const ['lc2.jpg', 'lc3.jpg', 'lc4.jpg', 'lc5.jpg'],
|
guideImages: const [
|
||||||
instructionText: l10n.manualYaoTipContent,
|
['assets/images/tutorial/tutorial_1.png'],
|
||||||
|
['assets/images/tutorial/tutorial_2.png'],
|
||||||
|
['assets/images/tutorial/tutorial_3.png'],
|
||||||
|
],
|
||||||
|
instructions: [
|
||||||
|
l10n.divinationManualGuideStep1,
|
||||||
|
l10n.divinationManualGuideStep2,
|
||||||
|
l10n.divinationManualGuideStep3,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -409,43 +419,63 @@ class _YaoSelectionCard extends StatelessWidget {
|
|||||||
int yaoIndex,
|
int yaoIndex,
|
||||||
void Function(int, YaoType) onSelect,
|
void Function(int, YaoType) onSelect,
|
||||||
) {
|
) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
|
||||||
final colors = Theme.of(context).colorScheme;
|
|
||||||
final options = <(String, YaoType, String)>[
|
|
||||||
(
|
|
||||||
'${DivinationTerms.yaoTypeLabels[YaoTypeLabel.youngYang]}(${DivinationTerms.youngYangSymbol})',
|
|
||||||
YaoType.youngYang,
|
|
||||||
'字字字',
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'${DivinationTerms.yaoTypeLabels[YaoTypeLabel.youngYin]}(${DivinationTerms.youngYinSymbol})',
|
|
||||||
YaoType.youngYin,
|
|
||||||
'花花花',
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'${DivinationTerms.yaoTypeLabels[YaoTypeLabel.oldYang]}(${DivinationTerms.oldYangSymbol})',
|
|
||||||
YaoType.oldYang,
|
|
||||||
'字字字',
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'${DivinationTerms.yaoTypeLabels[YaoTypeLabel.oldYin]}(${DivinationTerms.oldYinSymbol})',
|
|
||||||
YaoType.oldYin,
|
|
||||||
'花花花',
|
|
||||||
),
|
|
||||||
];
|
|
||||||
return showDialog<void>(
|
return showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
|
return _ThreeCoinSelectorDialog(
|
||||||
|
onConfirm: (yaoType) {
|
||||||
|
onSelect(yaoIndex, yaoType);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ThreeCoinSelectorDialog extends StatefulWidget {
|
||||||
|
const _ThreeCoinSelectorDialog({required this.onConfirm});
|
||||||
|
|
||||||
|
final void Function(YaoType) onConfirm;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_ThreeCoinSelectorDialog> createState() =>
|
||||||
|
_ThreeCoinSelectorDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ThreeCoinSelectorDialogState extends State<_ThreeCoinSelectorDialog> {
|
||||||
|
final List<bool> _coinStates = [false, false, false];
|
||||||
|
|
||||||
|
YaoType get _currentYaoType {
|
||||||
|
final huaCount = _coinStates.where((isHua) => isHua).length;
|
||||||
|
return switch (huaCount) {
|
||||||
|
0 => YaoType.oldYin,
|
||||||
|
1 => YaoType.youngYang,
|
||||||
|
2 => YaoType.youngYin,
|
||||||
|
3 => YaoType.oldYang,
|
||||||
|
_ => YaoType.undetermined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void _toggleCoin(int index) {
|
||||||
|
setState(() {
|
||||||
|
_coinStates[index] = !_coinStates[index];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
final colors = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
return Dialog(
|
return Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(AppSpacing.lg),
|
padding: const EdgeInsets.all(AppSpacing.lg),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -465,21 +495,16 @@ class _YaoSelectionCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: AppSpacing.md),
|
const SizedBox(height: AppSpacing.lg),
|
||||||
...options.map((option) {
|
Row(
|
||||||
return Padding(
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
padding: const EdgeInsets.only(bottom: AppSpacing.sm),
|
children: List.generate(3, (index) {
|
||||||
child: _YaoOptionCard(
|
return _FlippingCoin(
|
||||||
label: option.$1,
|
isHua: _coinStates[index],
|
||||||
pattern: option.$3,
|
onTap: () => _toggleCoin(index),
|
||||||
isSelected: false,
|
|
||||||
onTap: () {
|
|
||||||
onSelect(yaoIndex, option.$2);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
),
|
||||||
const SizedBox(height: AppSpacing.md),
|
const SizedBox(height: AppSpacing.md),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(AppSpacing.md),
|
padding: const EdgeInsets.all(AppSpacing.md),
|
||||||
@@ -487,129 +512,105 @@ class _YaoSelectionCard extends StatelessWidget {
|
|||||||
color: colors.surfaceContainerHighest,
|
color: colors.surfaceContainerHighest,
|
||||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||||
),
|
),
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
l10n.coinFaceGuideTitle,
|
|
||||||
style: Theme.of(context).textTheme.titleSmall
|
|
||||||
?.copyWith(
|
|
||||||
color: colors.onSurface,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: AppSpacing.sm),
|
|
||||||
ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/qigua/zihua.jpg',
|
|
||||||
width: double.infinity,
|
|
||||||
height: 120,
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
errorBuilder: (context, error, stackTrace) =>
|
|
||||||
Container(
|
|
||||||
height: 120,
|
|
||||||
color: colors.errorContainer,
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
child: Text(
|
||||||
l10n.divinationClose,
|
l10n.manualCoinSelectHint,
|
||||||
style: TextStyle(
|
style: Theme.of(
|
||||||
color: colors.onErrorContainer,
|
context,
|
||||||
|
).textTheme.bodySmall?.copyWith(color: colors.onSurfaceVariant),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: AppSpacing.lg),
|
||||||
),
|
SizedBox(
|
||||||
),
|
width: double.infinity,
|
||||||
),
|
child: FilledButton(
|
||||||
const SizedBox(height: AppSpacing.xs),
|
onPressed: () => widget.onConfirm(_currentYaoType),
|
||||||
Text(
|
child: Text(l10n.confirm),
|
||||||
l10n.coinFaceGuideDescription,
|
|
||||||
style: Theme.of(context).textTheme.bodySmall
|
|
||||||
?.copyWith(color: colors.onSurfaceVariant),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FlippingCoin extends StatefulWidget {
|
||||||
|
const _FlippingCoin({required this.isHua, required this.onTap});
|
||||||
|
|
||||||
|
final bool isHua;
|
||||||
|
final VoidCallback onTap;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_FlippingCoin> createState() => _FlippingCoinState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FlippingCoinState extends State<_FlippingCoin>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
late Animation<double> _animation;
|
||||||
|
bool _showHua = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_showHua = widget.isHua;
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
vsync: this,
|
||||||
|
);
|
||||||
|
_animation = Tween<double>(
|
||||||
|
begin: 0,
|
||||||
|
end: 1,
|
||||||
|
).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(_FlippingCoin oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (oldWidget.isHua != widget.isHua) {
|
||||||
|
if (widget.isHua != _showHua) {
|
||||||
|
_controller.forward().then((_) {
|
||||||
|
setState(() {
|
||||||
|
_showHua = widget.isHua;
|
||||||
|
});
|
||||||
|
_controller.reverse();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: widget.onTap,
|
||||||
|
child: AnimatedBuilder(
|
||||||
|
animation: _animation,
|
||||||
|
builder: (context, child) {
|
||||||
|
final angle = _animation.value * pi;
|
||||||
|
return Transform(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
transform: Matrix4.identity()
|
||||||
|
..setEntry(3, 2, 0.001)
|
||||||
|
..rotateY(angle),
|
||||||
|
child: ClipOval(
|
||||||
|
child: Image.asset(
|
||||||
|
_showHua
|
||||||
|
? 'assets/images/qigua/hua.jpg'
|
||||||
|
: 'assets/images/qigua/zi.jpg',
|
||||||
|
width: 80,
|
||||||
|
height: 80,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _YaoOptionCard extends StatelessWidget {
|
|
||||||
const _YaoOptionCard({
|
|
||||||
required this.label,
|
|
||||||
required this.pattern,
|
|
||||||
required this.isSelected,
|
|
||||||
required this.onTap,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String label;
|
|
||||||
final String pattern;
|
|
||||||
final bool isSelected;
|
|
||||||
final VoidCallback onTap;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final colors = Theme.of(context).colorScheme;
|
|
||||||
return Material(
|
|
||||||
color: isSelected ? colors.primaryContainer : colors.surface,
|
|
||||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
|
||||||
child: InkWell(
|
|
||||||
onTap: onTap,
|
|
||||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: AppSpacing.md,
|
|
||||||
vertical: AppSpacing.sm + 4,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
|
||||||
border: Border.all(
|
|
||||||
color: isSelected ? colors.primary : colors.outlineVariant,
|
|
||||||
width: isSelected ? 2 : 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
label,
|
|
||||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
|
||||||
color: isSelected
|
|
||||||
? colors.onPrimaryContainer
|
|
||||||
: colors.onSurface,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 2),
|
|
||||||
Text(
|
|
||||||
pattern,
|
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
|
||||||
color: isSelected
|
|
||||||
? colors.onPrimaryContainer.withValues(alpha: 0.7)
|
|
||||||
: colors.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Icon(
|
|
||||||
Icons.chevron_right,
|
|
||||||
color: isSelected
|
|
||||||
? colors.onPrimaryContainer
|
|
||||||
: colors.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,11 +80,15 @@
|
|||||||
"signBad": "Inauspicious",
|
"signBad": "Inauspicious",
|
||||||
"language": "Language",
|
"language": "Language",
|
||||||
"settingsTitle": "Settings",
|
"settingsTitle": "Settings",
|
||||||
"settingsSectionGeneral": "General",
|
"settingsSectionGeneral": "Preferences",
|
||||||
"settingsSectionQuickAccess": "Primary Menu",
|
"settingsSectionQuickAccess": "Primary Menu",
|
||||||
"settingsSectionAccount": "Account",
|
"settingsSectionAccount": "Account",
|
||||||
"settingsSectionPrivacy": "Privacy",
|
"settingsSectionPrivacy": "Privacy",
|
||||||
"settingsSectionNotification": "Notifications",
|
"settingsSectionNotification": "Notifications",
|
||||||
|
"settingsInterfaceLanguage": "Interface Language",
|
||||||
|
"settingsAiLanguage": "AI Response Language",
|
||||||
|
"settingsNotificationAllow": "Allow Notifications",
|
||||||
|
"settingsNotificationVibration": "Allow Vibration",
|
||||||
"settingsSectionAbout": "About",
|
"settingsSectionAbout": "About",
|
||||||
"settingsGeneralTitle": "General Settings",
|
"settingsGeneralTitle": "General Settings",
|
||||||
"settingsGeneralSubtitle": "Language: {currentLanguage}. Other fields are reserved to match profiles.settings.",
|
"settingsGeneralSubtitle": "Language: {currentLanguage}. Other fields are reserved to match profiles.settings.",
|
||||||
@@ -166,14 +170,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"settingsCoinCenterDescription": "Payment is not connected yet. The UI now shows packages and the recharge entry.",
|
"settingsCoinCenterDescription": "",
|
||||||
"settingsCoinRechargeSection": "Recharge Packages",
|
"settingsCoinRechargeSection": "Recharge Packages",
|
||||||
"settingsCoinPackBasic": "Starter Pack",
|
"settingsCoinPackBasic": "Starter Pack",
|
||||||
"settingsCoinPackPopular": "Popular Pack",
|
"settingsCoinPackPopular": "Popular Pack",
|
||||||
"settingsCoinPackPremium": "Premium Pack",
|
"settingsCoinPackPremium": "Premium Pack",
|
||||||
"settingsCoinPackPopularBadge": "Popular",
|
"settingsCoinPackPopularBadge": "Popular",
|
||||||
"settingsPurchaseButton": "Pay Now",
|
"settingsPurchaseButton": "Pay Now",
|
||||||
"settingsPurchasePending": "Payment is not connected yet",
|
"settingsPurchasePending": "",
|
||||||
"settingsCoinAmount": "{amount} credits",
|
"settingsCoinAmount": "{amount} credits",
|
||||||
"@settingsCoinAmount": {
|
"@settingsCoinAmount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@@ -226,7 +230,9 @@
|
|||||||
"divinationMethodTipManual": "Manual: Prepare three identical coins.",
|
"divinationMethodTipManual": "Manual: Prepare three identical coins.",
|
||||||
"divinationMethodTipRecommend": "Manual casting provides higher accuracy.",
|
"divinationMethodTipRecommend": "Manual casting provides higher accuracy.",
|
||||||
"divinationManualGuideTitle": "Manual Casting Tutorial",
|
"divinationManualGuideTitle": "Manual Casting Tutorial",
|
||||||
"divinationManualGuideInstruction": "Prepare three identical coins and cast six times following the guide.",
|
"divinationManualGuideStep1": "Left: Pattern side. Right: Inscription side. Prepare three identical coins or similar tokens.",
|
||||||
|
"divinationManualGuideStep2": "Hold the coins in both hands, think about your question, then toss them onto a table. Record how many inscription sides and pattern sides appear.",
|
||||||
|
"divinationManualGuideStep3": "Record each result by whether the inscription side or pattern side faces up. Repeat 6 times, recording from bottom to top.",
|
||||||
"divinationIAcknowledge": "I Understand",
|
"divinationIAcknowledge": "I Understand",
|
||||||
"divinationClose": "Close",
|
"divinationClose": "Close",
|
||||||
"divinationModify": "Modify",
|
"divinationModify": "Modify",
|
||||||
@@ -287,6 +293,7 @@
|
|||||||
"transitionPreparing": "Deriving...",
|
"transitionPreparing": "Deriving...",
|
||||||
"transitionDeriving": "Analyzing...",
|
"transitionDeriving": "Analyzing...",
|
||||||
"transitionDone": "Complete\nTap to view",
|
"transitionDone": "Complete\nTap to view",
|
||||||
|
"iChingTitle": "I Ching",
|
||||||
"processingCardQianTitle": "Qian • The Creative",
|
"processingCardQianTitle": "Qian • The Creative",
|
||||||
"processingCardQianQuote": "The movement of Heaven is full of power; thus the noble one makes himself strong and tireless.",
|
"processingCardQianQuote": "The movement of Heaven is full of power; thus the noble one makes himself strong and tireless.",
|
||||||
"processingCardDuiTitle": "Dui • The Joyous",
|
"processingCardDuiTitle": "Dui • The Joyous",
|
||||||
@@ -321,6 +328,7 @@
|
|||||||
"manualYaoInstruction": "Tap to view casting method and coin combination guide",
|
"manualYaoInstruction": "Tap to view casting method and coin combination guide",
|
||||||
"manualYaoTipTitle": "Tip",
|
"manualYaoTipTitle": "Tip",
|
||||||
"manualYaoTipContent": "Select from bottom to top, not top to bottom.\n\nCast three coins together, select once each time, six times total.",
|
"manualYaoTipContent": "Select from bottom to top, not top to bottom.\n\nCast three coins together, select once each time, six times total.",
|
||||||
|
"manualCoinSelectHint": "Tap coins to flip between inscription and pattern. Record your casting result.",
|
||||||
"autoScreenTitle": "Auto Casting",
|
"autoScreenTitle": "Auto Casting",
|
||||||
"autoSelectTime": "Select time",
|
"autoSelectTime": "Select time",
|
||||||
"autoCoinDivination": "Coin Casting",
|
"autoCoinDivination": "Coin Casting",
|
||||||
@@ -365,5 +373,33 @@
|
|||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"autoSelectTime": "Select Time",
|
"autoSelectTime": "Select Time",
|
||||||
"coinFaceGuideTitle": "Coin Face Guide",
|
"coinFaceGuideTitle": "Coin Face Guide",
|
||||||
"coinFaceGuideDescription": "字 = side with inscription\n花 = side with pattern"
|
"coinFaceGuideDescription": "Left: Pattern side. Right: Inscription side.",
|
||||||
|
"settingsInviteTitle": "My Invitation",
|
||||||
|
"settingsInviteSubtitle": "Invite friends, earn rewards together",
|
||||||
|
"settingsInviteMyCode": "My Invite Code",
|
||||||
|
"settingsInviteCopySuccess": "Invite code copied",
|
||||||
|
"settingsInviteCopied": "Copied",
|
||||||
|
"settingsInviteCopy": "Copy",
|
||||||
|
"settingsInviteStats": "Invited: {count} friend(s)",
|
||||||
|
"@settingsInviteStats": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {
|
||||||
|
"type": "int"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settingsInviteBindCode": "Bind Invite Code",
|
||||||
|
"settingsInviteBindHint": "Enter your friend's invite code",
|
||||||
|
"settingsInviteBindPlaceholder": "6-digit code",
|
||||||
|
"settingsInviteBindButton": "Bind",
|
||||||
|
"settingsInviteBindSuccess": "Invite code bound successfully",
|
||||||
|
"settingsInviteBindFailed": "Failed to bind invite code",
|
||||||
|
"settingsInviteGenerateTitle": "Generate My Invite Code",
|
||||||
|
"settingsInviteGenerateButton": "Generate My Invite Code",
|
||||||
|
"settingsInviteGenerateSuccess": "Invite code generated",
|
||||||
|
"settingsInviteEmptyTitle": "Invite Friends, Earn Rewards",
|
||||||
|
"settingsInviteEmptyDescription": "Each friend who registers using your invite code gives you bonus credits",
|
||||||
|
"settingsInviteInputLabel": "Enter invite code (optional)",
|
||||||
|
"settingsInviteInputHint": "Enter code to bind your inviter",
|
||||||
|
"settingsInviteInvalidCode": "Please enter a valid 6-character invite code"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ abstract class AppLocalizations {
|
|||||||
/// No description provided for @settingsSectionGeneral.
|
/// No description provided for @settingsSectionGeneral.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'通用设置'**
|
/// **'偏好设置'**
|
||||||
String get settingsSectionGeneral;
|
String get settingsSectionGeneral;
|
||||||
|
|
||||||
/// No description provided for @settingsSectionQuickAccess.
|
/// No description provided for @settingsSectionQuickAccess.
|
||||||
@@ -524,6 +524,30 @@ abstract class AppLocalizations {
|
|||||||
/// **'通知设置'**
|
/// **'通知设置'**
|
||||||
String get settingsSectionNotification;
|
String get settingsSectionNotification;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInterfaceLanguage.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'界面语言'**
|
||||||
|
String get settingsInterfaceLanguage;
|
||||||
|
|
||||||
|
/// No description provided for @settingsAiLanguage.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'AI 回复语言'**
|
||||||
|
String get settingsAiLanguage;
|
||||||
|
|
||||||
|
/// No description provided for @settingsNotificationAllow.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'允许通知'**
|
||||||
|
String get settingsNotificationAllow;
|
||||||
|
|
||||||
|
/// No description provided for @settingsNotificationVibration.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'允许振动'**
|
||||||
|
String get settingsNotificationVibration;
|
||||||
|
|
||||||
/// No description provided for @settingsSectionAbout.
|
/// No description provided for @settingsSectionAbout.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
@@ -584,12 +608,6 @@ abstract class AppLocalizations {
|
|||||||
/// **'点数可用于后续起卦与相关服务消费'**
|
/// **'点数可用于后续起卦与相关服务消费'**
|
||||||
String get settingsCoinHeroSubtitle;
|
String get settingsCoinHeroSubtitle;
|
||||||
|
|
||||||
/// No description provided for @settingsAiLanguage.
|
|
||||||
///
|
|
||||||
/// In zh, this message translates to:
|
|
||||||
/// **'AI 回复语言'**
|
|
||||||
String get settingsAiLanguage;
|
|
||||||
|
|
||||||
/// No description provided for @settingsAiLanguageHint.
|
/// No description provided for @settingsAiLanguageHint.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
@@ -845,7 +863,7 @@ abstract class AppLocalizations {
|
|||||||
/// No description provided for @settingsCoinCenterDescription.
|
/// No description provided for @settingsCoinCenterDescription.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'充值入口暂未接入支付逻辑,先展示套餐与购买流程入口。'**
|
/// **''**
|
||||||
String get settingsCoinCenterDescription;
|
String get settingsCoinCenterDescription;
|
||||||
|
|
||||||
/// No description provided for @settingsCoinRechargeSection.
|
/// No description provided for @settingsCoinRechargeSection.
|
||||||
@@ -887,7 +905,7 @@ abstract class AppLocalizations {
|
|||||||
/// No description provided for @settingsPurchasePending.
|
/// No description provided for @settingsPurchasePending.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'支付能力暂未接入'**
|
/// **''**
|
||||||
String get settingsPurchasePending;
|
String get settingsPurchasePending;
|
||||||
|
|
||||||
/// No description provided for @settingsCoinAmount.
|
/// No description provided for @settingsCoinAmount.
|
||||||
@@ -1118,11 +1136,23 @@ abstract class AppLocalizations {
|
|||||||
/// **'手动起卦教程'**
|
/// **'手动起卦教程'**
|
||||||
String get divinationManualGuideTitle;
|
String get divinationManualGuideTitle;
|
||||||
|
|
||||||
/// No description provided for @divinationManualGuideInstruction.
|
/// No description provided for @divinationManualGuideStep1.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'准备三枚同样铜钱,按页面引导连续完成六次摇卦。'**
|
/// **'左侧为花面,右侧为字面。准备三枚相同的钱币,任何类似款式均可。'**
|
||||||
String get divinationManualGuideInstruction;
|
String get divinationManualGuideStep1;
|
||||||
|
|
||||||
|
/// No description provided for @divinationManualGuideStep2.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'双手捧起钱币,闭目心中默念所问之事,然后抛掷钱币于桌面,记录字面和花面出现的次数。'**
|
||||||
|
String get divinationManualGuideStep2;
|
||||||
|
|
||||||
|
/// No description provided for @divinationManualGuideStep3.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'记录每次结果,按照「字面在上还是花面在上」记录。重复六次,从下往上记录。'**
|
||||||
|
String get divinationManualGuideStep3;
|
||||||
|
|
||||||
/// No description provided for @divinationIAcknowledge.
|
/// No description provided for @divinationIAcknowledge.
|
||||||
///
|
///
|
||||||
@@ -1382,100 +1412,106 @@ abstract class AppLocalizations {
|
|||||||
/// **'解卦完成\n点击查看'**
|
/// **'解卦完成\n点击查看'**
|
||||||
String get transitionDone;
|
String get transitionDone;
|
||||||
|
|
||||||
|
/// No description provided for @iChingTitle.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'周易'**
|
||||||
|
String get iChingTitle;
|
||||||
|
|
||||||
/// No description provided for @processingCardQianTitle.
|
/// No description provided for @processingCardQianTitle.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Qian • The Creative'**
|
/// **'乾 • 元亨利贞'**
|
||||||
String get processingCardQianTitle;
|
String get processingCardQianTitle;
|
||||||
|
|
||||||
/// No description provided for @processingCardQianQuote.
|
/// No description provided for @processingCardQianQuote.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'The movement of Heaven is full of power; thus the noble one makes himself strong and tireless.'**
|
/// **'天行健,君子以自强不息。'**
|
||||||
String get processingCardQianQuote;
|
String get processingCardQianQuote;
|
||||||
|
|
||||||
/// No description provided for @processingCardDuiTitle.
|
/// No description provided for @processingCardDuiTitle.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Dui • The Joyous'**
|
/// **'兑 • 亨利贞'**
|
||||||
String get processingCardDuiTitle;
|
String get processingCardDuiTitle;
|
||||||
|
|
||||||
/// No description provided for @processingCardDuiQuote.
|
/// No description provided for @processingCardDuiQuote.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Joy grounded in integrity brings openness, harmony, and right expression.'**
|
/// **'丽泽兑,君子以朋友讲习。'**
|
||||||
String get processingCardDuiQuote;
|
String get processingCardDuiQuote;
|
||||||
|
|
||||||
/// No description provided for @processingCardLiTitle.
|
/// No description provided for @processingCardLiTitle.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Li • The Clinging Fire'**
|
/// **'离 • 明两作亨利贞'**
|
||||||
String get processingCardLiTitle;
|
String get processingCardLiTitle;
|
||||||
|
|
||||||
/// No description provided for @processingCardLiQuote.
|
/// No description provided for @processingCardLiQuote.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'With clear brilliance, the great one illumines all directions.'**
|
/// **'大人以继明照于四方。'**
|
||||||
String get processingCardLiQuote;
|
String get processingCardLiQuote;
|
||||||
|
|
||||||
/// No description provided for @processingCardZhenTitle.
|
/// No description provided for @processingCardZhenTitle.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Zhen • The Arousing Thunder'**
|
/// **'震 • 亨震来虩虩,笑言哑哑'**
|
||||||
String get processingCardZhenTitle;
|
String get processingCardZhenTitle;
|
||||||
|
|
||||||
/// No description provided for @processingCardZhenQuote.
|
/// No description provided for @processingCardZhenQuote.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Shock awakens the heart; composure turns fear into growth.'**
|
/// **'震惊百里,惊远而惧迩也。'**
|
||||||
String get processingCardZhenQuote;
|
String get processingCardZhenQuote;
|
||||||
|
|
||||||
/// No description provided for @processingCardXunTitle.
|
/// No description provided for @processingCardXunTitle.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Xun • The Gentle Wind'**
|
/// **'巽 • 小亨利贞'**
|
||||||
String get processingCardXunTitle;
|
String get processingCardXunTitle;
|
||||||
|
|
||||||
/// No description provided for @processingCardXunQuote.
|
/// No description provided for @processingCardXunQuote.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Gentle penetration furthers progress and helps one meet the right people.'**
|
/// **'随风,君子以申命行事。'**
|
||||||
String get processingCardXunQuote;
|
String get processingCardXunQuote;
|
||||||
|
|
||||||
/// No description provided for @processingCardKanTitle.
|
/// No description provided for @processingCardKanTitle.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Kan • The Abysmal Water'**
|
/// **'坎 • 习坎有孚维心亨'**
|
||||||
String get processingCardKanTitle;
|
String get processingCardKanTitle;
|
||||||
|
|
||||||
/// No description provided for @processingCardKanQuote.
|
/// No description provided for @processingCardKanQuote.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'In danger, sincerity and disciplined action carry one through.'**
|
/// **'水流而不盈,行险而不失其信。'**
|
||||||
String get processingCardKanQuote;
|
String get processingCardKanQuote;
|
||||||
|
|
||||||
/// No description provided for @processingCardGenTitle.
|
/// No description provided for @processingCardGenTitle.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Gen • Keeping Still Mountain'**
|
/// **'艮 • 艮其背不获其身'**
|
||||||
String get processingCardGenTitle;
|
String get processingCardGenTitle;
|
||||||
|
|
||||||
/// No description provided for @processingCardGenQuote.
|
/// No description provided for @processingCardGenQuote.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Stillness at the proper time keeps one centered and steady in place.'**
|
/// **'时止则止,时行则行,动静不失其时。'**
|
||||||
String get processingCardGenQuote;
|
String get processingCardGenQuote;
|
||||||
|
|
||||||
/// No description provided for @processingCardKunTitle.
|
/// No description provided for @processingCardKunTitle.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'Kun • The Receptive Earth'**
|
/// **'坤 • 元亨利牝马之贞'**
|
||||||
String get processingCardKunTitle;
|
String get processingCardKunTitle;
|
||||||
|
|
||||||
/// No description provided for @processingCardKunQuote.
|
/// No description provided for @processingCardKunQuote.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'The Earth\'s condition is devoted receptivity; the noble one carries all with broad virtue.'**
|
/// **'地势坤,君子以厚德载物。'**
|
||||||
String get processingCardKunQuote;
|
String get processingCardKunQuote;
|
||||||
|
|
||||||
/// No description provided for @ganZhiInfo.
|
/// No description provided for @ganZhiInfo.
|
||||||
@@ -1586,6 +1622,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'请从下往上选,不是从上往下选。\n\n三枚铜钱一起摇,摇完一次选一次,一共摇六次。'**
|
/// **'请从下往上选,不是从上往下选。\n\n三枚铜钱一起摇,摇完一次选一次,一共摇六次。'**
|
||||||
String get manualYaoTipContent;
|
String get manualYaoTipContent;
|
||||||
|
|
||||||
|
/// No description provided for @manualCoinSelectHint.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'点击硬币可翻转,调整字面和花面。记录摇卦结果。'**
|
||||||
|
String get manualCoinSelectHint;
|
||||||
|
|
||||||
/// No description provided for @autoScreenTitle.
|
/// No description provided for @autoScreenTitle.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
@@ -1715,14 +1757,140 @@ abstract class AppLocalizations {
|
|||||||
/// No description provided for @coinFaceGuideTitle.
|
/// No description provided for @coinFaceGuideTitle.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'字花图片说明'**
|
/// **'字花对照说明'**
|
||||||
String get coinFaceGuideTitle;
|
String get coinFaceGuideTitle;
|
||||||
|
|
||||||
/// No description provided for @coinFaceGuideDescription.
|
/// No description provided for @coinFaceGuideDescription.
|
||||||
///
|
///
|
||||||
/// In zh, this message translates to:
|
/// In zh, this message translates to:
|
||||||
/// **'字=铜钱有字的一面\n花=铜钱有花纹的一面'**
|
/// **'左侧为花面,右侧为字面。'**
|
||||||
String get coinFaceGuideDescription;
|
String get coinFaceGuideDescription;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteTitle.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'我的邀请'**
|
||||||
|
String get settingsInviteTitle;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteSubtitle.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'邀请好友,共同获得奖励'**
|
||||||
|
String get settingsInviteSubtitle;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteMyCode.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'我的邀请码'**
|
||||||
|
String get settingsInviteMyCode;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteCopySuccess.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'邀请码已复制'**
|
||||||
|
String get settingsInviteCopySuccess;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteCopied.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'已复制'**
|
||||||
|
String get settingsInviteCopied;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteCopy.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'复制'**
|
||||||
|
String get settingsInviteCopy;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteStats.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'已邀请:{count} 位好友'**
|
||||||
|
String settingsInviteStats(int count);
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteBindCode.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'绑定邀请码'**
|
||||||
|
String get settingsInviteBindCode;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteBindHint.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'输入好友的邀请码'**
|
||||||
|
String get settingsInviteBindHint;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteBindPlaceholder.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'6位邀请码'**
|
||||||
|
String get settingsInviteBindPlaceholder;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteBindButton.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'绑定'**
|
||||||
|
String get settingsInviteBindButton;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteBindSuccess.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'邀请码绑定成功'**
|
||||||
|
String get settingsInviteBindSuccess;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteBindFailed.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'邀请码绑定失败'**
|
||||||
|
String get settingsInviteBindFailed;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteGenerateTitle.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'生成我的邀请码'**
|
||||||
|
String get settingsInviteGenerateTitle;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteGenerateButton.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'生成我的邀请码'**
|
||||||
|
String get settingsInviteGenerateButton;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteGenerateSuccess.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'邀请码生成成功'**
|
||||||
|
String get settingsInviteGenerateSuccess;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteEmptyTitle.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'邀请好友,获得奖励'**
|
||||||
|
String get settingsInviteEmptyTitle;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteEmptyDescription.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'每成功邀请一位好友注册,您将获得积分奖励'**
|
||||||
|
String get settingsInviteEmptyDescription;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteInputLabel.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'输入邀请码(选填)'**
|
||||||
|
String get settingsInviteInputLabel;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteInputHint.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'输入邀请码绑定您的邀请人'**
|
||||||
|
String get settingsInviteInputHint;
|
||||||
|
|
||||||
|
/// No description provided for @settingsInviteInvalidCode.
|
||||||
|
///
|
||||||
|
/// In zh, this message translates to:
|
||||||
|
/// **'请输入有效的6位邀请码'**
|
||||||
|
String get settingsInviteInvalidCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppLocalizationsDelegate
|
class _AppLocalizationsDelegate
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get settingsTitle => 'Settings';
|
String get settingsTitle => 'Settings';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsSectionGeneral => 'General';
|
String get settingsSectionGeneral => 'Preferences';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsSectionQuickAccess => 'Primary Menu';
|
String get settingsSectionQuickAccess => 'Primary Menu';
|
||||||
@@ -231,6 +231,18 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get settingsSectionNotification => 'Notifications';
|
String get settingsSectionNotification => 'Notifications';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInterfaceLanguage => 'Interface Language';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsAiLanguage => 'AI Response Language';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsNotificationAllow => 'Allow Notifications';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsNotificationVibration => 'Allow Vibration';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsSectionAbout => 'About';
|
String get settingsSectionAbout => 'About';
|
||||||
|
|
||||||
@@ -268,9 +280,6 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get settingsCoinHeroSubtitle =>
|
String get settingsCoinHeroSubtitle =>
|
||||||
'Credits will be used for casting and related services later.';
|
'Credits will be used for casting and related services later.';
|
||||||
|
|
||||||
@override
|
|
||||||
String get settingsAiLanguage => 'AI Response Language';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsAiLanguageHint =>
|
String get settingsAiLanguageHint =>
|
||||||
'This field will align with profiles.settings.preferences.ai_language once the real preference flow is connected.';
|
'This field will align with profiles.settings.preferences.ai_language once the real preference flow is connected.';
|
||||||
@@ -411,8 +420,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsCoinCenterDescription =>
|
String get settingsCoinCenterDescription => '';
|
||||||
'Payment is not connected yet. The UI now shows packages and the recharge entry.';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsCoinRechargeSection => 'Recharge Packages';
|
String get settingsCoinRechargeSection => 'Recharge Packages';
|
||||||
@@ -433,7 +441,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get settingsPurchaseButton => 'Pay Now';
|
String get settingsPurchaseButton => 'Pay Now';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsPurchasePending => 'Payment is not connected yet';
|
String get settingsPurchasePending => '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String settingsCoinAmount(int amount) {
|
String settingsCoinAmount(int amount) {
|
||||||
@@ -566,8 +574,16 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get divinationManualGuideTitle => 'Manual Casting Tutorial';
|
String get divinationManualGuideTitle => 'Manual Casting Tutorial';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get divinationManualGuideInstruction =>
|
String get divinationManualGuideStep1 =>
|
||||||
'Prepare three identical coins and cast six times following the guide.';
|
'Left: Pattern side. Right: Inscription side. Prepare three identical coins or similar tokens.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get divinationManualGuideStep2 =>
|
||||||
|
'Hold the coins in both hands, think about your question, then toss them onto a table. Record how many inscription sides and pattern sides appear.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get divinationManualGuideStep3 =>
|
||||||
|
'Record each result by whether the inscription side or pattern side faces up. Repeat 6 times, recording from bottom to top.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get divinationIAcknowledge => 'I Understand';
|
String get divinationIAcknowledge => 'I Understand';
|
||||||
@@ -703,6 +719,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get transitionDone => 'Complete\nTap to view';
|
String get transitionDone => 'Complete\nTap to view';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get iChingTitle => 'I Ching';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardQianTitle => 'Qian • The Creative';
|
String get processingCardQianTitle => 'Qian • The Creative';
|
||||||
|
|
||||||
@@ -815,6 +834,10 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get manualYaoTipContent =>
|
String get manualYaoTipContent =>
|
||||||
'Select from bottom to top, not top to bottom.\n\nCast three coins together, select once each time, six times total.';
|
'Select from bottom to top, not top to bottom.\n\nCast three coins together, select once each time, six times total.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get manualCoinSelectHint =>
|
||||||
|
'Tap coins to flip between inscription and pattern. Record your casting result.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get autoScreenTitle => 'Auto Casting';
|
String get autoScreenTitle => 'Auto Casting';
|
||||||
|
|
||||||
@@ -890,5 +913,72 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get coinFaceGuideDescription =>
|
String get coinFaceGuideDescription =>
|
||||||
'字 = side with inscription\n花 = side with pattern';
|
'Left: Pattern side. Right: Inscription side.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteTitle => 'My Invitation';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteSubtitle => 'Invite friends, earn rewards together';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteMyCode => 'My Invite Code';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteCopySuccess => 'Invite code copied';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteCopied => 'Copied';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteCopy => 'Copy';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String settingsInviteStats(int count) {
|
||||||
|
return 'Invited: $count friend(s)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindCode => 'Bind Invite Code';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindHint => 'Enter your friend\'s invite code';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindPlaceholder => '6-digit code';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindButton => 'Bind';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindSuccess => 'Invite code bound successfully';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindFailed => 'Failed to bind invite code';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteGenerateTitle => 'Generate My Invite Code';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteGenerateButton => 'Generate My Invite Code';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteGenerateSuccess => 'Invite code generated';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteEmptyTitle => 'Invite Friends, Earn Rewards';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteEmptyDescription =>
|
||||||
|
'Each friend who registers using your invite code gives you bonus credits';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteInputLabel => 'Enter invite code (optional)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteInputHint => 'Enter code to bind your inviter';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteInvalidCode =>
|
||||||
|
'Please enter a valid 6-character invite code';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
String get settingsTitle => '设置';
|
String get settingsTitle => '设置';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsSectionGeneral => '通用设置';
|
String get settingsSectionGeneral => '偏好设置';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsSectionQuickAccess => '一级菜单';
|
String get settingsSectionQuickAccess => '一级菜单';
|
||||||
@@ -229,6 +229,18 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get settingsSectionNotification => '通知设置';
|
String get settingsSectionNotification => '通知设置';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInterfaceLanguage => '界面语言';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsAiLanguage => 'AI 回复语言';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsNotificationAllow => '允许通知';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsNotificationVibration => '允许振动';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsSectionAbout => '关于';
|
String get settingsSectionAbout => '关于';
|
||||||
|
|
||||||
@@ -264,9 +276,6 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get settingsCoinHeroSubtitle => '点数可用于后续起卦与相关服务消费';
|
String get settingsCoinHeroSubtitle => '点数可用于后续起卦与相关服务消费';
|
||||||
|
|
||||||
@override
|
|
||||||
String get settingsAiLanguage => 'AI 回复语言';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsAiLanguageHint =>
|
String get settingsAiLanguageHint =>
|
||||||
'该字段将对齐 profiles.settings.preferences.ai_language,后续接入真实偏好设置。';
|
'该字段将对齐 profiles.settings.preferences.ai_language,后续接入真实偏好设置。';
|
||||||
@@ -403,7 +412,7 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsCoinCenterDescription => '充值入口暂未接入支付逻辑,先展示套餐与购买流程入口。';
|
String get settingsCoinCenterDescription => '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsCoinRechargeSection => '充值套餐';
|
String get settingsCoinRechargeSection => '充值套餐';
|
||||||
@@ -424,7 +433,7 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
String get settingsPurchaseButton => '立即支付';
|
String get settingsPurchaseButton => '立即支付';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get settingsPurchasePending => '支付能力暂未接入';
|
String get settingsPurchasePending => '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String settingsCoinAmount(int amount) {
|
String settingsCoinAmount(int amount) {
|
||||||
@@ -549,7 +558,15 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
String get divinationManualGuideTitle => '手动起卦教程';
|
String get divinationManualGuideTitle => '手动起卦教程';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get divinationManualGuideInstruction => '准备三枚同样铜钱,按页面引导连续完成六次摇卦。';
|
String get divinationManualGuideStep1 => '左侧为花面,右侧为字面。准备三枚相同的钱币,任何类似款式均可。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get divinationManualGuideStep2 =>
|
||||||
|
'双手捧起钱币,闭目心中默念所问之事,然后抛掷钱币于桌面,记录字面和花面出现的次数。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get divinationManualGuideStep3 =>
|
||||||
|
'记录每次结果,按照「字面在上还是花面在上」记录。重复六次,从下往上记录。';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get divinationIAcknowledge => '我知道了';
|
String get divinationIAcknowledge => '我知道了';
|
||||||
@@ -686,60 +703,55 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
String get transitionDone => '解卦完成\n点击查看';
|
String get transitionDone => '解卦完成\n点击查看';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardQianTitle => 'Qian • The Creative';
|
String get iChingTitle => '周易';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardQianQuote =>
|
String get processingCardQianTitle => '乾 • 元亨利贞';
|
||||||
'The movement of Heaven is full of power; thus the noble one makes himself strong and tireless.';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardDuiTitle => 'Dui • The Joyous';
|
String get processingCardQianQuote => '天行健,君子以自强不息。';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardDuiQuote =>
|
String get processingCardDuiTitle => '兑 • 亨利贞';
|
||||||
'Joy grounded in integrity brings openness, harmony, and right expression.';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardLiTitle => 'Li • The Clinging Fire';
|
String get processingCardDuiQuote => '丽泽兑,君子以朋友讲习。';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardLiQuote =>
|
String get processingCardLiTitle => '离 • 明两作亨利贞';
|
||||||
'With clear brilliance, the great one illumines all directions.';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardZhenTitle => 'Zhen • The Arousing Thunder';
|
String get processingCardLiQuote => '大人以继明照于四方。';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardZhenQuote =>
|
String get processingCardZhenTitle => '震 • 亨震来虩虩,笑言哑哑';
|
||||||
'Shock awakens the heart; composure turns fear into growth.';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardXunTitle => 'Xun • The Gentle Wind';
|
String get processingCardZhenQuote => '震惊百里,惊远而惧迩也。';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardXunQuote =>
|
String get processingCardXunTitle => '巽 • 小亨利贞';
|
||||||
'Gentle penetration furthers progress and helps one meet the right people.';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardKanTitle => 'Kan • The Abysmal Water';
|
String get processingCardXunQuote => '随风,君子以申命行事。';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardKanQuote =>
|
String get processingCardKanTitle => '坎 • 习坎有孚维心亨';
|
||||||
'In danger, sincerity and disciplined action carry one through.';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardGenTitle => 'Gen • Keeping Still Mountain';
|
String get processingCardKanQuote => '水流而不盈,行险而不失其信。';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardGenQuote =>
|
String get processingCardGenTitle => '艮 • 艮其背不获其身';
|
||||||
'Stillness at the proper time keeps one centered and steady in place.';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardKunTitle => 'Kun • The Receptive Earth';
|
String get processingCardGenQuote => '时止则止,时行则行,动静不失其时。';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get processingCardKunQuote =>
|
String get processingCardKunTitle => '坤 • 元亨利牝马之贞';
|
||||||
'The Earth\'s condition is devoted receptivity; the noble one carries all with broad virtue.';
|
|
||||||
|
@override
|
||||||
|
String get processingCardKunQuote => '地势坤,君子以厚德载物。';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get ganZhiInfo => '干支信息';
|
String get ganZhiInfo => '干支信息';
|
||||||
@@ -795,6 +807,9 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get manualYaoTipContent => '请从下往上选,不是从上往下选。\n\n三枚铜钱一起摇,摇完一次选一次,一共摇六次。';
|
String get manualYaoTipContent => '请从下往上选,不是从上往下选。\n\n三枚铜钱一起摇,摇完一次选一次,一共摇六次。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get manualCoinSelectHint => '点击硬币可翻转,调整字面和花面。记录摇卦结果。';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get autoScreenTitle => '自动起卦';
|
String get autoScreenTitle => '自动起卦';
|
||||||
|
|
||||||
@@ -865,8 +880,73 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
String get cancel => '取消';
|
String get cancel => '取消';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get coinFaceGuideTitle => '字花图片说明';
|
String get coinFaceGuideTitle => '字花对照说明';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get coinFaceGuideDescription => '字=铜钱有字的一面\n花=铜钱有花纹的一面';
|
String get coinFaceGuideDescription => '左侧为花面,右侧为字面。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteTitle => '我的邀请';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteSubtitle => '邀请好友,共同获得奖励';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteMyCode => '我的邀请码';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteCopySuccess => '邀请码已复制';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteCopied => '已复制';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteCopy => '复制';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String settingsInviteStats(int count) {
|
||||||
|
return '已邀请:$count 位好友';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindCode => '绑定邀请码';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindHint => '输入好友的邀请码';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindPlaceholder => '6位邀请码';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindButton => '绑定';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindSuccess => '邀请码绑定成功';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteBindFailed => '邀请码绑定失败';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteGenerateTitle => '生成我的邀请码';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteGenerateButton => '生成我的邀请码';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteGenerateSuccess => '邀请码生成成功';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteEmptyTitle => '邀请好友,获得奖励';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteEmptyDescription => '每成功邀请一位好友注册,您将获得积分奖励';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteInputLabel => '输入邀请码(选填)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteInputHint => '输入邀请码绑定您的邀请人';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsInviteInvalidCode => '请输入有效的6位邀请码';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,11 +80,15 @@
|
|||||||
"signBad": "下下签",
|
"signBad": "下下签",
|
||||||
"language": "语言",
|
"language": "语言",
|
||||||
"settingsTitle": "设置",
|
"settingsTitle": "设置",
|
||||||
"settingsSectionGeneral": "通用设置",
|
"settingsSectionGeneral": "偏好设置",
|
||||||
"settingsSectionQuickAccess": "一级菜单",
|
"settingsSectionQuickAccess": "一级菜单",
|
||||||
"settingsSectionAccount": "账户操作",
|
"settingsSectionAccount": "账户操作",
|
||||||
"settingsSectionPrivacy": "隐私设置",
|
"settingsSectionPrivacy": "隐私设置",
|
||||||
"settingsSectionNotification": "通知设置",
|
"settingsSectionNotification": "通知设置",
|
||||||
|
"settingsInterfaceLanguage": "界面语言",
|
||||||
|
"settingsAiLanguage": "AI回复语言",
|
||||||
|
"settingsNotificationAllow": "允许通知",
|
||||||
|
"settingsNotificationVibration": "允许振动",
|
||||||
"settingsSectionAbout": "关于",
|
"settingsSectionAbout": "关于",
|
||||||
"settingsGeneralTitle": "通用设置",
|
"settingsGeneralTitle": "通用设置",
|
||||||
"settingsGeneralSubtitle": "语言:{currentLanguage},其余字段按 profiles.settings 结构预留",
|
"settingsGeneralSubtitle": "语言:{currentLanguage},其余字段按 profiles.settings 结构预留",
|
||||||
@@ -166,14 +170,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"settingsCoinCenterDescription": "充值入口暂未接入支付逻辑,先展示套餐与购买流程入口。",
|
"settingsCoinCenterDescription": "",
|
||||||
"settingsCoinRechargeSection": "充值套餐",
|
"settingsCoinRechargeSection": "充值套餐",
|
||||||
"settingsCoinPackBasic": "入门补充包",
|
"settingsCoinPackBasic": "入门补充包",
|
||||||
"settingsCoinPackPopular": "常用加量包",
|
"settingsCoinPackPopular": "常用加量包",
|
||||||
"settingsCoinPackPremium": "高频进阶包",
|
"settingsCoinPackPremium": "高频进阶包",
|
||||||
"settingsCoinPackPopularBadge": "推荐",
|
"settingsCoinPackPopularBadge": "推荐",
|
||||||
"settingsPurchaseButton": "立即支付",
|
"settingsPurchaseButton": "立即支付",
|
||||||
"settingsPurchasePending": "支付能力暂未接入",
|
"settingsPurchasePending": "",
|
||||||
"settingsCoinAmount": "{amount} 点数",
|
"settingsCoinAmount": "{amount} 点数",
|
||||||
"@settingsCoinAmount": {
|
"@settingsCoinAmount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
@@ -226,7 +230,9 @@
|
|||||||
"divinationMethodTipManual": "手动起卦:需要准备三枚同样的铜钱或硬币。",
|
"divinationMethodTipManual": "手动起卦:需要准备三枚同样的铜钱或硬币。",
|
||||||
"divinationMethodTipRecommend": "推荐使用手动起卦,卦象解读准确概率更高。",
|
"divinationMethodTipRecommend": "推荐使用手动起卦,卦象解读准确概率更高。",
|
||||||
"divinationManualGuideTitle": "手动起卦教程",
|
"divinationManualGuideTitle": "手动起卦教程",
|
||||||
"divinationManualGuideInstruction": "准备三枚同样铜钱,按页面引导连续完成六次摇卦。",
|
"divinationManualGuideStep1": "左侧为花面,右侧为字面。准备三枚相同的钱币,任何类似款式均可。",
|
||||||
|
"divinationManualGuideStep2": "双手捧起钱币,闭目心中默念所问之事,然后抛掷钱币于桌面,记录字面和花面出现的次数。",
|
||||||
|
"divinationManualGuideStep3": "记录每次结果,按照「字面在上还是花面在上」记录。重复六次,从下往上记录。",
|
||||||
"divinationIAcknowledge": "我知道了",
|
"divinationIAcknowledge": "我知道了",
|
||||||
"divinationClose": "关闭",
|
"divinationClose": "关闭",
|
||||||
"divinationModify": "修改",
|
"divinationModify": "修改",
|
||||||
@@ -287,22 +293,23 @@
|
|||||||
"transitionPreparing": "天机推演中",
|
"transitionPreparing": "天机推演中",
|
||||||
"transitionDeriving": "正在解卦",
|
"transitionDeriving": "正在解卦",
|
||||||
"transitionDone": "解卦完成\n点击查看",
|
"transitionDone": "解卦完成\n点击查看",
|
||||||
"processingCardQianTitle": "Qian • The Creative",
|
"iChingTitle": "周易",
|
||||||
"processingCardQianQuote": "The movement of Heaven is full of power; thus the noble one makes himself strong and tireless.",
|
"processingCardQianTitle": "乾 • 元亨利贞",
|
||||||
"processingCardDuiTitle": "Dui • The Joyous",
|
"processingCardQianQuote": "天行健,君子以自强不息。",
|
||||||
"processingCardDuiQuote": "Joy grounded in integrity brings openness, harmony, and right expression.",
|
"processingCardDuiTitle": "兑 • 亨利贞",
|
||||||
"processingCardLiTitle": "Li • The Clinging Fire",
|
"processingCardDuiQuote": "丽泽兑,君子以朋友讲习。",
|
||||||
"processingCardLiQuote": "With clear brilliance, the great one illumines all directions.",
|
"processingCardLiTitle": "离 • 明两作亨利贞",
|
||||||
"processingCardZhenTitle": "Zhen • The Arousing Thunder",
|
"processingCardLiQuote": "大人以继明照于四方。",
|
||||||
"processingCardZhenQuote": "Shock awakens the heart; composure turns fear into growth.",
|
"processingCardZhenTitle": "震 • 亨震来虩虩,笑言哑哑",
|
||||||
"processingCardXunTitle": "Xun • The Gentle Wind",
|
"processingCardZhenQuote": "震惊百里,惊远而惧迩也。",
|
||||||
"processingCardXunQuote": "Gentle penetration furthers progress and helps one meet the right people.",
|
"processingCardXunTitle": "巽 • 小亨利贞",
|
||||||
"processingCardKanTitle": "Kan • The Abysmal Water",
|
"processingCardXunQuote": "随风,君子以申命行事。",
|
||||||
"processingCardKanQuote": "In danger, sincerity and disciplined action carry one through.",
|
"processingCardKanTitle": "坎 • 习坎有孚维心亨",
|
||||||
"processingCardGenTitle": "Gen • Keeping Still Mountain",
|
"processingCardKanQuote": "水流而不盈,行险而不失其信。",
|
||||||
"processingCardGenQuote": "Stillness at the proper time keeps one centered and steady in place.",
|
"processingCardGenTitle": "艮 • 艮其背不获其身",
|
||||||
"processingCardKunTitle": "Kun • The Receptive Earth",
|
"processingCardGenQuote": "时止则止,时行则行,动静不失其时。",
|
||||||
"processingCardKunQuote": "The Earth's condition is devoted receptivity; the noble one carries all with broad virtue.",
|
"processingCardKunTitle": "坤 • 元亨利牝马之贞",
|
||||||
|
"processingCardKunQuote": "地势坤,君子以厚德载物。",
|
||||||
"ganZhiInfo": "干支信息",
|
"ganZhiInfo": "干支信息",
|
||||||
"wuXingWangShuai": "五行旺衰",
|
"wuXingWangShuai": "五行旺衰",
|
||||||
"ganZhiKongWang": "空亡信息",
|
"ganZhiKongWang": "空亡信息",
|
||||||
@@ -321,6 +328,7 @@
|
|||||||
"manualYaoInstruction": "点击查看起卦方法与铜钱字花组合说明",
|
"manualYaoInstruction": "点击查看起卦方法与铜钱字花组合说明",
|
||||||
"manualYaoTipTitle": "提示",
|
"manualYaoTipTitle": "提示",
|
||||||
"manualYaoTipContent": "请从下往上选,不是从上往下选。\n\n三枚铜钱一起摇,摇完一次选一次,一共摇六次。",
|
"manualYaoTipContent": "请从下往上选,不是从上往下选。\n\n三枚铜钱一起摇,摇完一次选一次,一共摇六次。",
|
||||||
|
"manualCoinSelectHint": "点击硬币可翻转,调整字面和花面。记录摇卦结果。",
|
||||||
"autoScreenTitle": "自动起卦",
|
"autoScreenTitle": "自动起卦",
|
||||||
"autoSelectTime": "选择起卦时间",
|
"autoSelectTime": "选择起卦时间",
|
||||||
"autoCoinDivination": "铜钱摇卦",
|
"autoCoinDivination": "铜钱摇卦",
|
||||||
@@ -364,6 +372,34 @@
|
|||||||
"confirm": "确认",
|
"confirm": "确认",
|
||||||
"cancel": "取消",
|
"cancel": "取消",
|
||||||
"autoSelectTime": "选择时间",
|
"autoSelectTime": "选择时间",
|
||||||
"coinFaceGuideTitle": "字花图片说明",
|
"coinFaceGuideTitle": "字花对照说明",
|
||||||
"coinFaceGuideDescription": "字=铜钱有字的一面\n花=铜钱有花纹的一面"
|
"coinFaceGuideDescription": "左侧为花面,右侧为字面。",
|
||||||
|
"settingsInviteTitle": "我的邀请",
|
||||||
|
"settingsInviteSubtitle": "邀请好友,共同获得奖励",
|
||||||
|
"settingsInviteMyCode": "我的邀请码",
|
||||||
|
"settingsInviteCopySuccess": "邀请码已复制",
|
||||||
|
"settingsInviteCopied": "已复制",
|
||||||
|
"settingsInviteCopy": "复制",
|
||||||
|
"settingsInviteStats": "已邀请:{count} 位好友",
|
||||||
|
"@settingsInviteStats": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {
|
||||||
|
"type": "int"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settingsInviteBindCode": "绑定邀请码",
|
||||||
|
"settingsInviteBindHint": "输入好友的邀请码",
|
||||||
|
"settingsInviteBindPlaceholder": "6位邀请码",
|
||||||
|
"settingsInviteBindButton": "绑定",
|
||||||
|
"settingsInviteBindSuccess": "邀请码绑定成功",
|
||||||
|
"settingsInviteBindFailed": "邀请码绑定失败",
|
||||||
|
"settingsInviteGenerateTitle": "生成我的邀请码",
|
||||||
|
"settingsInviteGenerateButton": "生成我的邀请码",
|
||||||
|
"settingsInviteGenerateSuccess": "邀请码生成成功",
|
||||||
|
"settingsInviteEmptyTitle": "邀请好友,获得奖励",
|
||||||
|
"settingsInviteEmptyDescription": "每成功邀请一位好友注册,您将获得积分奖励",
|
||||||
|
"settingsInviteInputLabel": "输入邀请码(选填)",
|
||||||
|
"settingsInviteInputHint": "输入邀请码绑定您的邀请人",
|
||||||
|
"settingsInviteInvalidCode": "请输入有效的6位邀请码"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,24 @@ import '../../theme/app_color_palette.dart';
|
|||||||
import '../../theme/design_tokens.dart';
|
import '../../theme/design_tokens.dart';
|
||||||
|
|
||||||
class DivinationGuideImage extends StatelessWidget {
|
class DivinationGuideImage extends StatelessWidget {
|
||||||
const DivinationGuideImage({super.key, required this.path});
|
const DivinationGuideImage({super.key, required this.paths});
|
||||||
|
|
||||||
final String path;
|
final List<String> paths;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.lg),
|
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.lg),
|
||||||
child: Image.asset(path, fit: BoxFit.contain),
|
child: paths.length == 1
|
||||||
|
? Image.asset(paths.first, fit: BoxFit.contain)
|
||||||
|
: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
Expanded(child: Image.asset(paths[0], fit: BoxFit.contain)),
|
||||||
|
const SizedBox(width: AppSpacing.md),
|
||||||
|
Expanded(child: Image.asset(paths[1], fit: BoxFit.contain)),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,17 +76,31 @@ class DivinationInstructionCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DivinationGuideDialog extends StatelessWidget {
|
class DivinationGuideDialog extends StatefulWidget {
|
||||||
const DivinationGuideDialog({
|
const DivinationGuideDialog({
|
||||||
super.key,
|
super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.guideImages,
|
required this.guideImages,
|
||||||
required this.instructionText,
|
required this.instructions,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
final List<String> guideImages;
|
final List<List<String>> guideImages;
|
||||||
final String instructionText;
|
final List<String> instructions;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DivinationGuideDialog> createState() => _DivinationGuideDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DivinationGuideDialogState extends State<DivinationGuideDialog> {
|
||||||
|
final PageController _pageController = PageController();
|
||||||
|
int _currentPage = 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_pageController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -90,7 +113,7 @@ class DivinationGuideDialog extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(height: AppSpacing.lg),
|
const SizedBox(height: AppSpacing.lg),
|
||||||
Text(
|
Text(
|
||||||
title,
|
widget.title,
|
||||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
@@ -98,15 +121,25 @@ class DivinationGuideDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: AppSpacing.md),
|
const SizedBox(height: AppSpacing.md),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: PageView(
|
child: PageView.builder(
|
||||||
children: guideImages
|
controller: _pageController,
|
||||||
.map((path) => DivinationGuideImage(path: path))
|
onPageChanged: (index) {
|
||||||
.toList(),
|
setState(() {
|
||||||
|
_currentPage = index;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
itemCount: widget.guideImages.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return DivinationGuideImage(paths: widget.guideImages[index]);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(AppSpacing.lg),
|
padding: const EdgeInsets.all(AppSpacing.lg),
|
||||||
child: Text(instructionText),
|
child: Text(
|
||||||
|
widget.instructions[_currentPage],
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(
|
padding: const EdgeInsets.fromLTRB(
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ abstract final class DivinationTerms {
|
|||||||
|
|
||||||
static const yinYang = {true: '阳', false: '阴'};
|
static const yinYang = {true: '阳', false: '阴'};
|
||||||
|
|
||||||
|
static const ziHua = {true: '字', false: '花'};
|
||||||
|
|
||||||
static const wuXing = ['木', '火', '土', '金', '水'];
|
static const wuXing = ['木', '火', '土', '金', '水'];
|
||||||
|
|
||||||
static const yuanZhi = '元';
|
static const yuanZhi = '元';
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ flutter:
|
|||||||
assets:
|
assets:
|
||||||
- assets/images/logo.png
|
- assets/images/logo.png
|
||||||
- assets/images/qigua/
|
- assets/images/qigua/
|
||||||
|
- assets/images/tutorial/
|
||||||
- assets/legal/en/
|
- assets/legal/en/
|
||||||
- assets/legal/zh/
|
- assets/legal/zh/
|
||||||
|
|
||||||
|
|||||||