Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/core/config/protected_routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ class ProtectedRoutes {
/// The token is sent when the user is authenticated; silently skipped for guests.
static const List<String> optionalPaths = [
'/plans/{planId}/days',
// Series list/detail: sends auth when logged in so the response includes
// user-enriched fields like `progress` and `partner`.
'/series',
'/series/{id}',
'/series/featured',
'/author/groups',
// Group detail + members: sends auth when logged in so fields like
// `is_group_enrolled` reflect the current user (anonymous GET → false).
Expand Down
1 change: 1 addition & 0 deletions lib/core/l10n/app_bo.arb
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@
"group_links_title": "འབྲེལ་ཐག",
"group_and_more_links": "དང་འབྲེལ་ཐག་གཞན་ {count}",
"group_practice_with_us": "ང་ཚོ་དང་མཉམ་དུ་སྒོམ་གྱི།",
"series_practicing_with_group": "{groupName} དང་མཉམ་དུ་ཉམས་ལེན་བྱེད",
"group_join_to_contribute": "བསགས་གྲངས་སྐྱེལ་ཆེད་ཞུགས།",
"group_accumulator_join_error": "བསགས་གྲངས་ལ་ཞུགས་མ་ཐུབ། ཡང་བསྐྱར་ཚོད་ལྟ་གནང་རོགས།",
"group_accumulator_participants": "མཉམ་ཞུགས་པ་ {count}",
Expand Down
8 changes: 8 additions & 0 deletions lib/core/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,14 @@
"group_links_title": "Links",
"group_and_more_links": "and {count} more links",
"group_practice_with_us": "Practice with us",
"series_practicing_with_group": "Practicing with {groupName}",
"@series_practicing_with_group": {
"placeholders": {
"groupName": {
"type": "String"
}
}
},
"group_change_practice_title": "Change group practice",
"group_change_practice_message": "You are already practicing this plan with another group. Would you like to change your practice group?",
"group_join_to_contribute": "Join to contribute",
Expand Down
1 change: 1 addition & 0 deletions lib/core/l10n/app_hi.arb
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@
"group_links_title": "लिंक",
"group_and_more_links": "और {count} और लिंक",
"group_practice_with_us": "हमारे साथ अभ्यास करें",
"series_practicing_with_group": "{groupName} के साथ अभ्यास",
"group_join_to_contribute": "योगदान के लिए शामिल हों",
"group_accumulator_join_error": "संचय में शामिल होने में असमर्थ। कृपया पुनः प्रयास करें।",
"group_accumulator_participants": "{count} प्रतिभागी",
Expand Down
1 change: 1 addition & 0 deletions lib/core/l10n/app_mn.arb
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@
"group_links_title": "Холбоосууд",
"group_and_more_links": "болон дахиад {count} холбоос",
"group_practice_with_us": "Бидэнтэй хамт дадлага хий",
"series_practicing_with_group": "{groupName}-тай хамт дадлага хийж байна",
"group_join_to_contribute": "Хувь нэмэр оруулахын тулд нэгдэх",
"group_accumulator_join_error": "Хуримтлалд нэгдэх боломжгүй байна. Дахин оролдоно уу.",
"group_accumulator_participants": "{count} оролцогч",
Expand Down
1 change: 1 addition & 0 deletions lib/core/l10n/app_ne.arb
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@
"group_links_title": "लिङ्कहरू",
"group_and_more_links": "र अरू {count} लिङ्कहरू",
"group_practice_with_us": "हामीसँग अभ्यास गर्नुहोस्",
"series_practicing_with_group": "{groupName} सँग अभ्यास",
"group_join_to_contribute": "योगदानका लागि सामेल हुनुहोस्",
"group_accumulator_join_error": "संचयमा सामेल हुन असमर्थ। कृपया फेरि प्रयास गर्नुहोस्।",
"group_accumulator_participants": "{count} सहभागी",
Expand Down
1 change: 1 addition & 0 deletions lib/core/l10n/app_zh.arb
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@
"group_links_title": "連結",
"group_and_more_links": "及另外 {count} 個連結",
"group_practice_with_us": "與我們一起修行",
"series_practicing_with_group": "與 {groupName} 一起修行",
"group_join_to_contribute": "加入以貢獻",
"group_accumulator_join_error": "無法加入累積,請再試一次。",
"group_accumulator_participants": "{count} 位參與者",
Expand Down
6 changes: 6 additions & 0 deletions lib/core/l10n/generated/app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3010,6 +3010,12 @@ abstract class AppLocalizations {
/// **'Practice with us'**
String get group_practice_with_us;

/// No description provided for @series_practicing_with_group.
///
/// In en, this message translates to:
/// **'Practicing with {groupName}'**
String series_practicing_with_group(String groupName);

/// No description provided for @group_change_practice_title.
///
/// In en, this message translates to:
Expand Down
5 changes: 5 additions & 0 deletions lib/core/l10n/generated/app_localizations_bo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1660,6 +1660,11 @@ class AppLocalizationsBo extends AppLocalizations {
@override
String get group_practice_with_us => 'ང་ཚོ་དང་མཉམ་དུ་སྒོམ་གྱི།';

@override
String series_practicing_with_group(String groupName) {
return '$groupName དང་མཉམ་དུ་ཉམས་ལེན་བྱེད';
}

@override
String get group_change_practice_title => 'Change group practice';

Expand Down
5 changes: 5 additions & 0 deletions lib/core/l10n/generated/app_localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,11 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get group_practice_with_us => 'Practice with us';

@override
String series_practicing_with_group(String groupName) {
return 'Practicing with $groupName';
}

@override
String get group_change_practice_title => 'Change group practice';

Expand Down
5 changes: 5 additions & 0 deletions lib/core/l10n/generated/app_localizations_hi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1652,6 +1652,11 @@ class AppLocalizationsHi extends AppLocalizations {
@override
String get group_practice_with_us => 'हमारे साथ अभ्यास करें';

@override
String series_practicing_with_group(String groupName) {
return '$groupName के साथ अभ्यास';
}

@override
String get group_change_practice_title => 'Change group practice';

Expand Down
5 changes: 5 additions & 0 deletions lib/core/l10n/generated/app_localizations_mn.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,11 @@ class AppLocalizationsMn extends AppLocalizations {
@override
String get group_practice_with_us => 'Бидэнтэй хамт дадлага хий';

@override
String series_practicing_with_group(String groupName) {
return '$groupName-тай хамт дадлага хийж байна';
}

@override
String get group_change_practice_title => 'Change group practice';

Expand Down
5 changes: 5 additions & 0 deletions lib/core/l10n/generated/app_localizations_ne.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1660,6 +1660,11 @@ class AppLocalizationsNe extends AppLocalizations {
@override
String get group_practice_with_us => 'हामीसँग अभ्यास गर्नुहोस्';

@override
String series_practicing_with_group(String groupName) {
return '$groupName सँग अभ्यास';
}

@override
String get group_change_practice_title => 'Change group practice';

Expand Down
5 changes: 5 additions & 0 deletions lib/core/l10n/generated/app_localizations_zh.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1565,6 +1565,11 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get group_practice_with_us => '與我們一起修行';

@override
String series_practicing_with_group(String groupName) {
return '與 $groupName 一起修行';
}

@override
String get group_change_practice_title => 'Change group practice';

Expand Down
6 changes: 4 additions & 2 deletions lib/features/home/data/datasource/home_local_datasource.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@ class HomeLocalDatasource {

String featuredDayKey(String language) => 'featured_day:$language';
String tagsKey(String language) => 'tags:$language';
// v3: entries cached before the request sent auth lack progress/partner.
String featuredSeriesKey(String language, int limit) =>
'featured_series:$language:$limit';
'featured_series:v3:$language:$limit';
String seriesListKey(String language) => 'series_list:$language';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 seriesListKey was not given a version suffix, unlike featuredSeriesKey (→ v3) and seriesByIdKey (→ v2). The same staleness issue applies: a device with a series_list:$language entry from before auth was wired to the endpoint will serve the cached models (missing progressJson/partnerJson) on the initial render, so the progress bar and partner row won't appear until the background refresh completes. Adding a version token (e.g. 'series_list:v2:$language') would invalidate those entries on first launch.

String seriesByIdKey(String language, String id) => 'series:$language:$id';
String seriesByIdKey(String language, String id) =>
'series:v2:$language:$id';
String todayEventsKey(String language) => 'today_events:$language';
String verseOfDayKey(String language) => 'verse_of_day:$language';
String routineInfoKey(String userId) => 'routine_info:$userId';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class SeriesRemoteDatasource {
final response = await dio.get(
'/series',
queryParameters: params.toQueryParams(),
options: Options(extra: {'no_cache': true}),
);

if (response.statusCode == 200) {
Expand All @@ -96,6 +97,7 @@ class SeriesRemoteDatasource {
final response = await dio.get(
'/series',
queryParameters: {'language': language},
options: Options(extra: {'no_cache': true}),
);

if (response.statusCode == 200) {
Expand Down Expand Up @@ -123,6 +125,7 @@ class SeriesRemoteDatasource {
final response = await dio.get(
'/series/$id',
queryParameters: {'language': language},
options: Options(extra: {'no_cache': true}),
);

if (response.statusCode == 200) {
Expand Down
36 changes: 36 additions & 0 deletions lib/features/home/data/models/series_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class SeriesModel {
final List<PlansModel> plans;
final int totalDays;
final Map<String, dynamic>? groupJson;
final Map<String, dynamic>? progressJson;
final Map<String, dynamic>? partnerJson;

SeriesModel({
required this.id,
Expand All @@ -67,6 +69,8 @@ class SeriesModel {
this.plans = const [],
this.totalDays = 0,
this.groupJson,
this.progressJson,
this.partnerJson,
});

String? get imageUrl => image?.displayUrl;
Expand Down Expand Up @@ -121,6 +125,14 @@ class SeriesModel {
json['group'] is Map<String, dynamic>
? json['group'] as Map<String, dynamic>
: null,
progressJson:
json['progress'] is Map<String, dynamic>
? json['progress'] as Map<String, dynamic>
: null,
partnerJson:
json['partner'] is Map<String, dynamic>
? json['partner'] as Map<String, dynamic>
: null,
);
}

Expand All @@ -139,6 +151,8 @@ class SeriesModel {
'plans': plans.map((p) => p.toJson()).toList(),
'total_days': totalDays,
'group': groupJson,
'progress': progressJson,
'partner': partnerJson,
};
}

Expand All @@ -158,6 +172,28 @@ class SeriesModel {
endDate: endDate,
plans: plans.map((p) => p.toEntity()).toList(),
group: _parseGroup(language),
progress: _parseProgress(),
partner: _parsePartner(),
);
}

SeriesProgress? _parseProgress() {
final p = progressJson;
if (p == null) return null;
return SeriesProgress(
totalDayCount: (p['total_day_count'] as num?)?.toInt() ?? 0,
currentDayNumber: (p['current_day_number'] as num?)?.toInt() ?? 0,
);
}

SeriesPartner? _parsePartner() {
final p = partnerJson;
if (p == null) return null;
final name = p['group_name'] as String? ?? '';
if (name.isEmpty) return null;
return SeriesPartner(
groupName: name,
groupImage: p['group_image'] as String?,
);
}

Expand Down
27 changes: 27 additions & 0 deletions lib/features/home/domain/entities/series.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,29 @@ class SeriesGroup {
});
}

class SeriesProgress {
final int totalDayCount;
final int currentDayNumber;

const SeriesProgress({
required this.totalDayCount,
required this.currentDayNumber,
});

/// 0..1 completion ratio, safe against zero/overflowing day counts.
double get fraction {
if (totalDayCount <= 0) return 0;
return (currentDayNumber / totalDayCount).clamp(0.0, 1.0);
}
}

class SeriesPartner {
final String groupName;
final String? groupImage;

const SeriesPartner({required this.groupName, this.groupImage});
}

class Series {
final String id;
final String title;
Expand All @@ -37,6 +60,8 @@ class Series {
final DateTime? endDate;
final List<Plan> plans;
final SeriesGroup? group;
final SeriesProgress? progress;
final SeriesPartner? partner;

const Series({
required this.id,
Expand All @@ -52,6 +77,8 @@ class Series {
this.endDate,
this.plans = const [],
this.group,
this.progress,
this.partner,
});

/// Smallest cover URL — legacy string-only callers.
Expand Down
Loading
Loading