main #14
@@ -213,6 +213,7 @@ export default function OnboardingScreen() {
|
|||||||
onSkip={onSkip}
|
onSkip={onSkip}
|
||||||
onBack={onBack}
|
onBack={onBack}
|
||||||
showBackButton={stepIndex > 0}
|
showBackButton={stepIndex > 0}
|
||||||
|
userName={name}
|
||||||
>
|
>
|
||||||
{currentStep.type === 'name' && (
|
{currentStep.type === 'name' && (
|
||||||
<NameInputStep
|
<NameInputStep
|
||||||
@@ -233,7 +234,7 @@ export default function OnboardingScreen() {
|
|||||||
|
|
||||||
{currentStep.type === 'reminder' && (
|
{currentStep.type === 'reminder' && (
|
||||||
<ReminderStep
|
<ReminderStep
|
||||||
value={reminderTimes}
|
value={Math.max(1, reminderTimes)}
|
||||||
onChange={setReminderTimes}
|
onChange={setReminderTimes}
|
||||||
onFinish={onFinish}
|
onFinish={onFinish}
|
||||||
onSkip={() => {
|
onSkip={() => {
|
||||||
|
|||||||
@@ -95,8 +95,7 @@ export function NameInputStep({ value, onChangeText, onNext }: NameInputStepProp
|
|||||||
blurOnSubmit={true}
|
blurOnSubmit={true}
|
||||||
onSubmitEditing={() => {
|
onSubmitEditing={() => {
|
||||||
Keyboard.dismiss();
|
Keyboard.dismiss();
|
||||||
// 有输入时,“完成”直接进入下一步,避免真机卡在键盘上
|
// 不再自動跳頁,僅收起鍵盤;前進需點擊底部 ➡️
|
||||||
if (value.trim().length > 0) onNext();
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import React from 'react';
|
import React, { useRef, useEffect } from 'react';
|
||||||
import { View, StyleSheet, SafeAreaView, TouchableOpacity, StatusBar, Text, Image, Platform } from 'react-native';
|
import { View, StyleSheet, SafeAreaView, TouchableOpacity, StatusBar, Text, Image, Platform, Animated, Easing } from 'react-native';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { OnboardingColors, OnboardingFont } from '@/constants/OnboardingTheme';
|
import { OnboardingColors, OnboardingFont } from '@/constants/OnboardingTheme';
|
||||||
|
|
||||||
|
const TRANSITION_OFFSET = 24;
|
||||||
|
const TRANSITION_DURATION = 280;
|
||||||
|
|
||||||
interface OnboardingLayoutProps {
|
interface OnboardingLayoutProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
title?: string;
|
title?: string;
|
||||||
@@ -11,6 +14,8 @@ interface OnboardingLayoutProps {
|
|||||||
onSkip: () => void;
|
onSkip: () => void;
|
||||||
onBack?: () => void;
|
onBack?: () => void;
|
||||||
showBackButton?: boolean;
|
showBackButton?: boolean;
|
||||||
|
/** 用户名字,仅在名字步骤之后的第一个问题(currentStep === 1)且非空时显示招呼语 */
|
||||||
|
userName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OnboardingLayout({
|
export function OnboardingLayout({
|
||||||
@@ -20,9 +25,48 @@ export function OnboardingLayout({
|
|||||||
totalSteps,
|
totalSteps,
|
||||||
onSkip,
|
onSkip,
|
||||||
onBack,
|
onBack,
|
||||||
showBackButton = false
|
showBackButton = false,
|
||||||
|
userName = '',
|
||||||
}: OnboardingLayoutProps) {
|
}: OnboardingLayoutProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const showGreeting = currentStep === 1 && userName.trim().length > 0;
|
||||||
|
const displayName = userName.trim();
|
||||||
|
const prevStepRef = useRef(currentStep);
|
||||||
|
const isFirstRenderRef = useRef(true);
|
||||||
|
const translateX = useRef(new Animated.Value(0)).current;
|
||||||
|
const opacity = useRef(new Animated.Value(1)).current;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isFirstRenderRef.current) {
|
||||||
|
isFirstRenderRef.current = false;
|
||||||
|
prevStepRef.current = currentStep;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (prevStepRef.current === currentStep) return;
|
||||||
|
|
||||||
|
const direction = currentStep > prevStepRef.current ? 'forward' : 'back';
|
||||||
|
prevStepRef.current = currentStep;
|
||||||
|
|
||||||
|
const startX = direction === 'forward' ? TRANSITION_OFFSET : -TRANSITION_OFFSET;
|
||||||
|
translateX.setValue(startX);
|
||||||
|
opacity.setValue(0.72);
|
||||||
|
|
||||||
|
Animated.parallel([
|
||||||
|
Animated.timing(translateX, {
|
||||||
|
toValue: 0,
|
||||||
|
duration: TRANSITION_DURATION,
|
||||||
|
useNativeDriver: true,
|
||||||
|
easing: Easing.out(Easing.cubic),
|
||||||
|
}),
|
||||||
|
Animated.timing(opacity, {
|
||||||
|
toValue: 1,
|
||||||
|
duration: TRANSITION_DURATION,
|
||||||
|
useNativeDriver: true,
|
||||||
|
easing: Easing.out(Easing.cubic),
|
||||||
|
}),
|
||||||
|
]).start();
|
||||||
|
}, [currentStep, translateX, opacity]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<StatusBar barStyle="dark-content" />
|
<StatusBar barStyle="dark-content" />
|
||||||
@@ -49,16 +93,29 @@ export function OnboardingLayout({
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Title & Progress Row */}
|
{/* Title & Progress Row(名字步骤后第一步且名字非空时显示招呼语 + 问题) */}
|
||||||
<View style={styles.titleRow}>
|
<View style={styles.titleRow}>
|
||||||
|
<View style={styles.titleBlock}>
|
||||||
|
{showGreeting && (
|
||||||
|
<Text style={styles.greetingText}>{t('onboardingSurvey.greeting', { name: displayName })}</Text>
|
||||||
|
)}
|
||||||
<Text style={styles.questionTitle}>{title}</Text>
|
<Text style={styles.questionTitle}>{title}</Text>
|
||||||
|
</View>
|
||||||
<Text style={styles.progressText}>({currentStep}/{totalSteps})</Text>
|
<Text style={styles.progressText}>({currentStep}/{totalSteps})</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content:step 切换时滑动 + 淡入 */}
|
||||||
<View style={styles.content}>
|
<Animated.View
|
||||||
|
style={[
|
||||||
|
styles.content,
|
||||||
|
{
|
||||||
|
opacity,
|
||||||
|
transform: [{ translateX }],
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</View>
|
</Animated.View>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -114,13 +171,22 @@ const styles = StyleSheet.create({
|
|||||||
alignItems: 'flex-end',
|
alignItems: 'flex-end',
|
||||||
paddingHorizontal: 20,
|
paddingHorizontal: 20,
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
marginBottom: 20,
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
titleBlock: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
},
|
||||||
|
greetingText: {
|
||||||
|
fontSize: 22,
|
||||||
|
color: OnboardingColors.questionTitle,
|
||||||
|
fontFamily: OnboardingFont.question,
|
||||||
|
marginBottom: 4,
|
||||||
},
|
},
|
||||||
questionTitle: {
|
questionTitle: {
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
color: OnboardingColors.questionTitle,
|
color: OnboardingColors.questionTitle,
|
||||||
fontFamily: OnboardingFont.question,
|
fontFamily: OnboardingFont.question,
|
||||||
flex: 1,
|
|
||||||
},
|
},
|
||||||
progressText: {
|
progressText: {
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ export function ReminderStep({ value, onChange, onFinish }: ReminderStepProps) {
|
|||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
|
|
||||||
const handleReduce = () => {
|
const handleReduce = () => {
|
||||||
// 允许 0~5;0 表示关闭每日提醒
|
// 本页最小为 1;不接收提醒请使用右上角 Skip
|
||||||
if (value > 0) onChange(value - 1);
|
if (value > 1) onChange(value - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
@@ -36,7 +36,9 @@ export function ReminderStep({ value, onChange, onFinish }: ReminderStepProps) {
|
|||||||
|
|
||||||
<View style={styles.numberWrapper}>
|
<View style={styles.numberWrapper}>
|
||||||
<Text style={styles.numberText}>{value}</Text>
|
<Text style={styles.numberText}>{value}</Text>
|
||||||
<Text style={styles.unitText}>{t('dailyReminder.timesUnit')}</Text>
|
<Text style={styles.unitText}>
|
||||||
|
{value === 1 ? t('dailyReminder.timesUnitSingular') : t('dailyReminder.timesUnit')}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<TouchableOpacity onPress={handleAdd} activeOpacity={0.7}>
|
<TouchableOpacity onPress={handleAdd} activeOpacity={0.7}>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import React from 'react';
|
|||||||
import { View, StyleSheet, TouchableOpacity, ScrollView, Text } from 'react-native';
|
import { View, StyleSheet, TouchableOpacity, ScrollView, Text } from 'react-native';
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import { OnboardingColors, OnboardingFont } from '@/constants/OnboardingTheme';
|
import { OnboardingColors, OnboardingFont } from '@/constants/OnboardingTheme';
|
||||||
import SelectedIcon from '@/assets/images/icon/selected_icon.svg';
|
|
||||||
import BtnNotClicked from '@/assets/images/icon/btn_Notclicked.svg';
|
import BtnNotClicked from '@/assets/images/icon/btn_Notclicked.svg';
|
||||||
import BtnClicked from '@/assets/images/icon/btn_clicked.svg';
|
import BtnClicked from '@/assets/images/icon/btn_clicked.svg';
|
||||||
|
|
||||||
@@ -39,16 +38,11 @@ export function SelectionStep({ options, selectedIds, onToggle, onNext, onSkip }
|
|||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
key={option.id}
|
key={option.id}
|
||||||
style={styles.optionCard}
|
style={[styles.optionCard, isSelected && styles.optionCardSelected]}
|
||||||
onPress={() => onToggle(option.id)}
|
onPress={() => onToggle(option.id)}
|
||||||
activeOpacity={0.7}
|
activeOpacity={0.7}
|
||||||
>
|
>
|
||||||
<Text style={styles.optionText}>{option.label}</Text>
|
<Text style={styles.optionText}>{option.label}</Text>
|
||||||
{isSelected && (
|
|
||||||
<View style={styles.iconWrapper}>
|
|
||||||
<SelectedIcon width={20} height={20} />
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -67,7 +61,7 @@ export function SelectionStep({ options, selectedIds, onToggle, onNext, onSkip }
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingTop: 20,
|
paddingTop: 8,
|
||||||
},
|
},
|
||||||
scroll: {
|
scroll: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@@ -82,7 +76,7 @@ const styles = StyleSheet.create({
|
|||||||
borderRadius: 20,
|
borderRadius: 20,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'center',
|
||||||
paddingHorizontal: 24,
|
paddingHorizontal: 24,
|
||||||
marginBottom: 12,
|
marginBottom: 12,
|
||||||
shadowColor: '#000',
|
shadowColor: '#000',
|
||||||
@@ -91,15 +85,14 @@ const styles = StyleSheet.create({
|
|||||||
shadowRadius: 10,
|
shadowRadius: 10,
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
},
|
},
|
||||||
|
optionCardSelected: {
|
||||||
|
backgroundColor: OnboardingColors.cardSelected,
|
||||||
|
},
|
||||||
optionText: {
|
optionText: {
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color: OnboardingColors.textPrimary,
|
color: OnboardingColors.textPrimary,
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
fontFamily: OnboardingFont.question,
|
fontFamily: OnboardingFont.question,
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
iconWrapper: {
|
|
||||||
marginLeft: 10,
|
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"q4Desc": "You can skip. We’ll stay with you along the way."
|
"q4Desc": "You can skip. We’ll stay with you along the way."
|
||||||
},
|
},
|
||||||
"onboardingSurvey": {
|
"onboardingSurvey": {
|
||||||
|
"greeting": "Hi {{name}},",
|
||||||
"steps": {
|
"steps": {
|
||||||
"name": { "title": "What should we call you?", "placeholder": "Mama" },
|
"name": { "title": "What should we call you?", "placeholder": "Mama" },
|
||||||
"status": {
|
"status": {
|
||||||
@@ -115,6 +116,7 @@
|
|||||||
"dailyReminder": {
|
"dailyReminder": {
|
||||||
"title": "Daily Reminder",
|
"title": "Daily Reminder",
|
||||||
"timesUnit": "times",
|
"timesUnit": "times",
|
||||||
|
"timesUnitSingular": "time",
|
||||||
"pushLabel": "Push Reminder",
|
"pushLabel": "Push Reminder",
|
||||||
"ok": "Ok",
|
"ok": "Ok",
|
||||||
"minus": "Decrease",
|
"minus": "Decrease",
|
||||||
@@ -183,7 +185,7 @@
|
|||||||
"progress": "{{current}}/{{total}}",
|
"progress": "{{current}}/{{total}}",
|
||||||
"next": "下一步",
|
"next": "下一步",
|
||||||
"skip": "跳過",
|
"skip": "跳過",
|
||||||
"skipAll": "跳過整個引導",
|
"skipAll": "跳過",
|
||||||
"q1Title": "你最近的感受更接近哪一種?",
|
"q1Title": "你最近的感受更接近哪一種?",
|
||||||
"q1Desc": "沒有對錯,你可以跳過,之後也能慢慢調整。",
|
"q1Desc": "沒有對錯,你可以跳過,之後也能慢慢調整。",
|
||||||
"q2Title": "你更希望獲得哪種支持?",
|
"q2Title": "你更希望獲得哪種支持?",
|
||||||
@@ -194,6 +196,7 @@
|
|||||||
"q4Desc": "你可以直接跳過,我們會在之後繼續陪你。"
|
"q4Desc": "你可以直接跳過,我們會在之後繼續陪你。"
|
||||||
},
|
},
|
||||||
"onboardingSurvey": {
|
"onboardingSurvey": {
|
||||||
|
"greeting": "{{name}},你好",
|
||||||
"steps": {
|
"steps": {
|
||||||
"name": { "title": "我可以怎麼稱呼你?", "placeholder": "媽媽" },
|
"name": { "title": "我可以怎麼稱呼你?", "placeholder": "媽媽" },
|
||||||
"status": {
|
"status": {
|
||||||
@@ -284,6 +287,7 @@
|
|||||||
"dailyReminder": {
|
"dailyReminder": {
|
||||||
"title": "每日提醒",
|
"title": "每日提醒",
|
||||||
"timesUnit": "次",
|
"timesUnit": "次",
|
||||||
|
"timesUnitSingular": "次",
|
||||||
"pushLabel": "推送提醒",
|
"pushLabel": "推送提醒",
|
||||||
"ok": "確定",
|
"ok": "確定",
|
||||||
"minus": "減少次數",
|
"minus": "減少次數",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"progress": "{{current}}/{{total}}",
|
"progress": "{{current}}/{{total}}",
|
||||||
"next": "Next",
|
"next": "Next",
|
||||||
"skip": "Skip",
|
"skip": "Skip",
|
||||||
"skipAll": "Skip onboarding",
|
"skipAll": "Skip",
|
||||||
"q1Title": "How are you feeling lately?",
|
"q1Title": "How are you feeling lately?",
|
||||||
"q1Desc": "No right or wrong. You can skip and adjust later.",
|
"q1Desc": "No right or wrong. You can skip and adjust later.",
|
||||||
"q2Title": "What kind of support do you want?",
|
"q2Title": "What kind of support do you want?",
|
||||||
@@ -59,6 +59,7 @@
|
|||||||
"dailyReminder": {
|
"dailyReminder": {
|
||||||
"title": "Daily Reminder",
|
"title": "Daily Reminder",
|
||||||
"timesUnit": "times",
|
"timesUnit": "times",
|
||||||
|
"timesUnitSingular": "time",
|
||||||
"pushLabel": "Push Reminder",
|
"pushLabel": "Push Reminder",
|
||||||
"ok": "Ok",
|
"ok": "Ok",
|
||||||
"minus": "Decrease",
|
"minus": "Decrease",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"progress": "{{current}}/{{total}}",
|
"progress": "{{current}}/{{total}}",
|
||||||
"next": "Siguiente",
|
"next": "Siguiente",
|
||||||
"skip": "Saltar",
|
"skip": "Saltar",
|
||||||
"skipAll": "Saltar introducción",
|
"skipAll": "Saltar",
|
||||||
"q1Title": "¿Cómo te sientes últimamente?",
|
"q1Title": "¿Cómo te sientes últimamente?",
|
||||||
"q1Desc": "No hay respuestas correctas. Puedes saltar y ajustar después.",
|
"q1Desc": "No hay respuestas correctas. Puedes saltar y ajustar después.",
|
||||||
"q2Title": "¿Qué tipo de apoyo quieres?",
|
"q2Title": "¿Qué tipo de apoyo quieres?",
|
||||||
@@ -57,6 +57,7 @@
|
|||||||
"dailyReminder": {
|
"dailyReminder": {
|
||||||
"title": "Recordatorio diario",
|
"title": "Recordatorio diario",
|
||||||
"timesUnit": "veces",
|
"timesUnit": "veces",
|
||||||
|
"timesUnitSingular": "vez",
|
||||||
"pushLabel": "Recordatorio Push",
|
"pushLabel": "Recordatorio Push",
|
||||||
"ok": "Ok",
|
"ok": "Ok",
|
||||||
"minus": "Disminuir",
|
"minus": "Disminuir",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"progress": "{{current}}/{{total}}",
|
"progress": "{{current}}/{{total}}",
|
||||||
"next": "Próximo",
|
"next": "Próximo",
|
||||||
"skip": "Pular",
|
"skip": "Pular",
|
||||||
"skipAll": "Pular introdução",
|
"skipAll": "Pular",
|
||||||
"q1Title": "Como você tem se sentido ultimamente?",
|
"q1Title": "Como você tem se sentido ultimamente?",
|
||||||
"q1Desc": "Não há certo ou errado. Você pode pular e ajustar depois.",
|
"q1Desc": "Não há certo ou errado. Você pode pular e ajustar depois.",
|
||||||
"q2Title": "Que tipo de apoio você quer?",
|
"q2Title": "Que tipo de apoio você quer?",
|
||||||
@@ -57,6 +57,7 @@
|
|||||||
"dailyReminder": {
|
"dailyReminder": {
|
||||||
"title": "Lembrete diário",
|
"title": "Lembrete diário",
|
||||||
"timesUnit": "vezes",
|
"timesUnit": "vezes",
|
||||||
|
"timesUnitSingular": "vez",
|
||||||
"pushLabel": "Lembrete Push",
|
"pushLabel": "Lembrete Push",
|
||||||
"ok": "Ok",
|
"ok": "Ok",
|
||||||
"minus": "Diminuir",
|
"minus": "Diminuir",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"progress": "{{current}}/{{total}}",
|
"progress": "{{current}}/{{total}}",
|
||||||
"next": "下一步",
|
"next": "下一步",
|
||||||
"skip": "跳过",
|
"skip": "跳过",
|
||||||
"skipAll": "跳过整个引导",
|
"skipAll": "跳过",
|
||||||
"q1Title": "你最近的感受更接近哪一种?",
|
"q1Title": "你最近的感受更接近哪一种?",
|
||||||
"q1Desc": "没有对错,你可以跳过,之后也可以慢慢调整。",
|
"q1Desc": "没有对错,你可以跳过,之后也可以慢慢调整。",
|
||||||
"q2Title": "你更希望获得哪种支持?",
|
"q2Title": "你更希望获得哪种支持?",
|
||||||
@@ -60,6 +60,7 @@
|
|||||||
"dailyReminder": {
|
"dailyReminder": {
|
||||||
"title": "每日提醒",
|
"title": "每日提醒",
|
||||||
"timesUnit": "次",
|
"timesUnit": "次",
|
||||||
|
"timesUnitSingular": "次",
|
||||||
"pushLabel": "推送提醒",
|
"pushLabel": "推送提醒",
|
||||||
"ok": "确定",
|
"ok": "确定",
|
||||||
"minus": "减少次数",
|
"minus": "减少次数",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"progress": "{{current}}/{{total}}",
|
"progress": "{{current}}/{{total}}",
|
||||||
"next": "下一步",
|
"next": "下一步",
|
||||||
"skip": "跳過",
|
"skip": "跳過",
|
||||||
"skipAll": "跳過整個引導",
|
"skipAll": "跳過",
|
||||||
"q1Title": "你最近的感受更接近哪一種?",
|
"q1Title": "你最近的感受更接近哪一種?",
|
||||||
"q1Desc": "沒有對錯,你可以跳過,之後也能慢慢調整。",
|
"q1Desc": "沒有對錯,你可以跳過,之後也能慢慢調整。",
|
||||||
"q2Title": "你更希望獲得哪種支持?",
|
"q2Title": "你更希望獲得哪種支持?",
|
||||||
@@ -57,6 +57,7 @@
|
|||||||
"dailyReminder": {
|
"dailyReminder": {
|
||||||
"title": "每日提醒",
|
"title": "每日提醒",
|
||||||
"timesUnit": "次",
|
"timesUnit": "次",
|
||||||
|
"timesUnitSingular": "次",
|
||||||
"pushLabel": "推送提醒",
|
"pushLabel": "推送提醒",
|
||||||
"ok": "確定",
|
"ok": "確定",
|
||||||
"minus": "減少次數",
|
"minus": "減少次數",
|
||||||
|
|||||||
Reference in New Issue
Block a user