Implement husband-wife connection dialogue and theme support for learn articles

This commit is contained in:
2026-01-05 17:09:15 -06:00
parent 02d25d0cc7
commit 96655f9a74
36 changed files with 3849 additions and 819 deletions

View File

@@ -166,7 +166,13 @@ class CycleEntry extends HiveObject {
String? husbandNotes; // Separate notes for husband
@HiveField(29)
bool? intimacyProtected; // null = no intimacy, true = protected, false = unprotected
bool? intimacyProtected; // null = no selection, true = protected, false = unprotected
@HiveField(30, defaultValue: false)
bool usedPantyliner;
@HiveField(31, defaultValue: 0)
int pantylinerCount;
CycleEntry({
required this.id,
@@ -199,6 +205,8 @@ class CycleEntry extends HiveObject {
required this.createdAt,
required this.updatedAt,
this.husbandNotes,
this.usedPantyliner = false,
this.pantylinerCount = 0,
});
List<bool> get _symptomsList => [
@@ -261,6 +269,8 @@ class CycleEntry extends HiveObject {
DateTime? createdAt,
DateTime? updatedAt,
String? husbandNotes,
bool? usedPantyliner,
int? pantylinerCount,
}) {
return CycleEntry(
id: id ?? this.id,
@@ -293,6 +303,8 @@ class CycleEntry extends HiveObject {
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? DateTime.now(),
husbandNotes: husbandNotes ?? this.husbandNotes,
usedPantyliner: usedPantyliner ?? this.usedPantyliner,
pantylinerCount: pantylinerCount ?? this.pantylinerCount,
);
}
}

View File

@@ -47,13 +47,15 @@ class CycleEntryAdapter extends TypeAdapter<CycleEntry> {
createdAt: fields[20] as DateTime,
updatedAt: fields[21] as DateTime,
husbandNotes: fields[28] as String?,
usedPantyliner: fields[30] == null ? false : fields[30] as bool,
pantylinerCount: fields[31] == null ? 0 : fields[31] as int,
);
}
@override
void write(BinaryWriter writer, CycleEntry obj) {
writer
..writeByte(30)
..writeByte(32)
..writeByte(0)
..write(obj.id)
..writeByte(1)
@@ -113,7 +115,11 @@ class CycleEntryAdapter extends TypeAdapter<CycleEntry> {
..writeByte(28)
..write(obj.husbandNotes)
..writeByte(29)
..write(obj.intimacyProtected);
..write(obj.intimacyProtected)
..writeByte(30)
..write(obj.usedPantyliner)
..writeByte(31)
..write(obj.pantylinerCount);
}
@override

View File

@@ -0,0 +1,67 @@
import 'package:hive/hive.dart';
import 'package:uuid/uuid.dart';
part 'teaching_plan.g.dart';
@HiveType(typeId: 10)
class TeachingPlan {
@HiveField(0)
final String id;
@HiveField(1)
final String topic;
@HiveField(2)
final String scriptureReference;
@HiveField(3)
final String notes;
@HiveField(4)
final DateTime date;
@HiveField(5)
final bool isCompleted;
TeachingPlan({
required this.id,
required this.topic,
required this.scriptureReference,
required this.notes,
required this.date,
this.isCompleted = false,
});
TeachingPlan copyWith({
String? topic,
String? scriptureReference,
String? notes,
DateTime? date,
bool? isCompleted,
}) {
return TeachingPlan(
id: id,
topic: topic ?? this.topic,
scriptureReference: scriptureReference ?? this.scriptureReference,
notes: notes ?? this.notes,
date: date ?? this.date,
isCompleted: isCompleted ?? this.isCompleted,
);
}
factory TeachingPlan.create({
required String topic,
required String scriptureReference,
required String notes,
required DateTime date,
}) {
return TeachingPlan(
id: const Uuid().v4(),
topic: topic,
scriptureReference: scriptureReference,
notes: notes,
date: date,
isCompleted: false,
);
}
}

View File

@@ -0,0 +1,56 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'teaching_plan.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class TeachingPlanAdapter extends TypeAdapter<TeachingPlan> {
@override
final int typeId = 10;
@override
TeachingPlan read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return TeachingPlan(
id: fields[0] as String,
topic: fields[1] as String,
scriptureReference: fields[2] as String,
notes: fields[3] as String,
date: fields[4] as DateTime,
isCompleted: fields[5] as bool,
);
}
@override
void write(BinaryWriter writer, TeachingPlan obj) {
writer
..writeByte(6)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.topic)
..writeByte(2)
..write(obj.scriptureReference)
..writeByte(3)
..write(obj.notes)
..writeByte(4)
..write(obj.date)
..writeByte(5)
..write(obj.isCompleted);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is TeachingPlanAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -1,4 +1,5 @@
import 'package:hive/hive.dart';
import 'teaching_plan.dart';
part 'user_profile.g.dart';
@@ -184,6 +185,12 @@ class UserProfile extends HiveObject {
@HiveField(15, defaultValue: false)
bool isIrregularCycle;
@HiveField(41, defaultValue: 21)
int minCycleLength;
@HiveField(42, defaultValue: 40)
int maxCycleLength;
@HiveField(16, defaultValue: BibleTranslation.esv)
BibleTranslation bibleTranslation;
@@ -262,6 +269,39 @@ class UserProfile extends HiveObject {
@HiveField(40, defaultValue: false)
bool showPadTimerSeconds;
@HiveField(43, defaultValue: false)
bool notifyPad1Hour;
@HiveField(44, defaultValue: false)
bool notifyPad2Hours;
@HiveField(45)
String? privacyPin;
@HiveField(46, defaultValue: false)
bool isBioProtected;
@HiveField(47, defaultValue: false)
bool isHistoryProtected;
@HiveField(48, defaultValue: false)
bool notifyPad30Mins;
@HiveField(49, defaultValue: true)
bool notifyPadNow;
@HiveField(50, defaultValue: false)
bool isLogProtected;
@HiveField(51, defaultValue: false)
bool isCalendarProtected;
@HiveField(52, defaultValue: false)
bool isSuppliesProtected;
@HiveField(53)
List<TeachingPlan>? teachingPlans;
UserProfile({
required this.id,
required this.name,
@@ -277,6 +317,8 @@ class UserProfile extends HiveObject {
this.partnerName,
this.role = UserRole.wife,
this.isIrregularCycle = false,
this.minCycleLength = 21,
this.maxCycleLength = 40,
this.bibleTranslation = BibleTranslation.esv,
this.favoriteFoods,
this.isDataShared = false,
@@ -303,6 +345,17 @@ class UserProfile extends HiveObject {
this.padSupplies,
this.showPadTimerMinutes = true,
this.showPadTimerSeconds = false,
this.notifyPad1Hour = false,
this.notifyPad2Hours = false,
this.privacyPin,
this.isBioProtected = false,
this.isHistoryProtected = false,
this.notifyPad30Mins = false,
this.notifyPadNow = true,
this.isLogProtected = false,
this.isCalendarProtected = false,
this.isSuppliesProtected = false,
this.teachingPlans,
});
/// Check if user is married
@@ -343,6 +396,8 @@ class UserProfile extends HiveObject {
String? partnerName,
UserRole? role,
bool? isIrregularCycle,
int? minCycleLength,
int? maxCycleLength,
BibleTranslation? bibleTranslation,
List<String>? favoriteFoods,
bool? isDataShared,
@@ -369,6 +424,17 @@ class UserProfile extends HiveObject {
List<SupplyItem>? padSupplies,
bool? showPadTimerMinutes,
bool? showPadTimerSeconds,
bool? notifyPad1Hour,
bool? notifyPad2Hours,
String? privacyPin,
bool? isBioProtected,
bool? isHistoryProtected,
bool? notifyPad30Mins,
bool? notifyPadNow,
bool? isLogProtected,
bool? isCalendarProtected,
bool? isSuppliesProtected,
List<TeachingPlan>? teachingPlans,
}) {
return UserProfile(
id: id ?? this.id,
@@ -386,6 +452,8 @@ class UserProfile extends HiveObject {
partnerName: partnerName ?? this.partnerName,
role: role ?? this.role,
isIrregularCycle: isIrregularCycle ?? this.isIrregularCycle,
minCycleLength: minCycleLength ?? this.minCycleLength,
maxCycleLength: maxCycleLength ?? this.maxCycleLength,
bibleTranslation: bibleTranslation ?? this.bibleTranslation,
favoriteFoods: favoriteFoods ?? this.favoriteFoods,
isDataShared: isDataShared ?? this.isDataShared,
@@ -412,6 +480,17 @@ class UserProfile extends HiveObject {
padSupplies: padSupplies ?? this.padSupplies,
showPadTimerMinutes: showPadTimerMinutes ?? this.showPadTimerMinutes,
showPadTimerSeconds: showPadTimerSeconds ?? this.showPadTimerSeconds,
notifyPad1Hour: notifyPad1Hour ?? this.notifyPad1Hour,
notifyPad2Hours: notifyPad2Hours ?? this.notifyPad2Hours,
privacyPin: privacyPin ?? this.privacyPin,
isBioProtected: isBioProtected ?? this.isBioProtected,
isHistoryProtected: isHistoryProtected ?? this.isHistoryProtected,
notifyPad30Mins: notifyPad30Mins ?? this.notifyPad30Mins,
notifyPadNow: notifyPadNow ?? this.notifyPadNow,
isLogProtected: isLogProtected ?? this.isLogProtected,
isCalendarProtected: isCalendarProtected ?? this.isCalendarProtected,
isSuppliesProtected: isSuppliesProtected ?? this.isSuppliesProtected,
teachingPlans: teachingPlans ?? this.teachingPlans,
);
}
}

View File

@@ -76,6 +76,8 @@ class UserProfileAdapter extends TypeAdapter<UserProfile> {
partnerName: fields[12] as String?,
role: fields[14] == null ? UserRole.wife : fields[14] as UserRole,
isIrregularCycle: fields[15] == null ? false : fields[15] as bool,
minCycleLength: fields[41] == null ? 21 : fields[41] as int,
maxCycleLength: fields[42] == null ? 40 : fields[42] as int,
bibleTranslation: fields[16] == null
? BibleTranslation.esv
: fields[16] as BibleTranslation,
@@ -105,13 +107,24 @@ class UserProfileAdapter extends TypeAdapter<UserProfile> {
padSupplies: (fields[38] as List?)?.cast<SupplyItem>(),
showPadTimerMinutes: fields[39] == null ? true : fields[39] as bool,
showPadTimerSeconds: fields[40] == null ? false : fields[40] as bool,
notifyPad1Hour: fields[43] == null ? false : fields[43] as bool,
notifyPad2Hours: fields[44] == null ? false : fields[44] as bool,
privacyPin: fields[45] as String?,
isBioProtected: fields[46] == null ? false : fields[46] as bool,
isHistoryProtected: fields[47] == null ? false : fields[47] as bool,
notifyPad30Mins: fields[48] == null ? false : fields[48] as bool,
notifyPadNow: fields[49] == null ? true : fields[49] as bool,
isLogProtected: fields[50] == null ? false : fields[50] as bool,
isCalendarProtected: fields[51] == null ? false : fields[51] as bool,
isSuppliesProtected: fields[52] == null ? false : fields[52] as bool,
teachingPlans: (fields[53] as List?)?.cast<TeachingPlan>(),
);
}
@override
void write(BinaryWriter writer, UserProfile obj) {
writer
..writeByte(40)
..writeByte(53)
..writeByte(0)
..write(obj.id)
..writeByte(1)
@@ -142,6 +155,10 @@ class UserProfileAdapter extends TypeAdapter<UserProfile> {
..write(obj.role)
..writeByte(15)
..write(obj.isIrregularCycle)
..writeByte(41)
..write(obj.minCycleLength)
..writeByte(42)
..write(obj.maxCycleLength)
..writeByte(16)
..write(obj.bibleTranslation)
..writeByte(17)
@@ -191,7 +208,29 @@ class UserProfileAdapter extends TypeAdapter<UserProfile> {
..writeByte(39)
..write(obj.showPadTimerMinutes)
..writeByte(40)
..write(obj.showPadTimerSeconds);
..write(obj.showPadTimerSeconds)
..writeByte(43)
..write(obj.notifyPad1Hour)
..writeByte(44)
..write(obj.notifyPad2Hours)
..writeByte(45)
..write(obj.privacyPin)
..writeByte(46)
..write(obj.isBioProtected)
..writeByte(47)
..write(obj.isHistoryProtected)
..writeByte(48)
..write(obj.notifyPad30Mins)
..writeByte(49)
..write(obj.notifyPadNow)
..writeByte(50)
..write(obj.isLogProtected)
..writeByte(51)
..write(obj.isCalendarProtected)
..writeByte(52)
..write(obj.isSuppliesProtected)
..writeByte(53)
..write(obj.teachingPlans);
}
@override