chore: make activity bookmark ID final to prevent bookmarking the same activity twice (#2310)
This commit is contained in:
parent
e3961db0d6
commit
d4ce298866
6 changed files with 73 additions and 71 deletions
|
|
@ -100,9 +100,7 @@ class ActivityPlanCardState extends State<ActivityPlanCard> {
|
|||
|
||||
Future<ActivityPlanModel> _addBookmark(ActivityPlanModel activity) async {
|
||||
try {
|
||||
final uniqueID =
|
||||
"${activity.title.replaceAll(RegExp(r'\s+'), '-')}-${DateTime.now().millisecondsSinceEpoch}";
|
||||
return BookmarkedActivitiesRepo.save(activity, uniqueID);
|
||||
return BookmarkedActivitiesRepo.save(activity);
|
||||
} catch (e, stack) {
|
||||
debugger(when: kDebugMode);
|
||||
ErrorHandler.logError(e: e, s: stack, data: activity.toJson());
|
||||
|
|
@ -116,9 +114,8 @@ class ActivityPlanCardState extends State<ActivityPlanCard> {
|
|||
}
|
||||
|
||||
Future<void> _removeBookmark() async {
|
||||
if (widget.activity.bookmarkId == null) return;
|
||||
try {
|
||||
BookmarkedActivitiesRepo.remove(widget.activity.bookmarkId!);
|
||||
BookmarkedActivitiesRepo.remove(widget.activity.bookmarkId);
|
||||
} catch (e, stack) {
|
||||
debugger(when: kDebugMode);
|
||||
ErrorHandler.logError(e: e, s: stack, data: widget.activity.toJson());
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart';
|
|||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
|
||||
class ActivityPlanModel {
|
||||
final String bookmarkId;
|
||||
final ActivityPlanRequest req;
|
||||
String title;
|
||||
String learningObjective;
|
||||
String instructions;
|
||||
List<Vocab> vocab;
|
||||
String? imageURL;
|
||||
String? bookmarkId;
|
||||
|
||||
ActivityPlanModel({
|
||||
required this.req,
|
||||
|
|
@ -18,9 +18,8 @@ class ActivityPlanModel {
|
|||
required this.learningObjective,
|
||||
required this.instructions,
|
||||
required this.vocab,
|
||||
this.bookmarkId,
|
||||
this.imageURL,
|
||||
});
|
||||
}) : bookmarkId = req.hashCode.toString();
|
||||
|
||||
factory ActivityPlanModel.fromJson(Map<String, dynamic> json) {
|
||||
return ActivityPlanModel(
|
||||
|
|
@ -32,7 +31,6 @@ class ActivityPlanModel {
|
|||
json[ModelKey.activityPlanVocab].map((vocab) => Vocab.fromJson(vocab)),
|
||||
),
|
||||
imageURL: json[ModelKey.activityPlanImageURL],
|
||||
bookmarkId: json[ModelKey.activityPlanBookmarkId],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -77,8 +75,7 @@ class ActivityPlanModel {
|
|||
other.learningObjective == learningObjective &&
|
||||
other.instructions == instructions &&
|
||||
listEquals(other.vocab, vocab) &&
|
||||
other.imageURL == imageURL &&
|
||||
other.bookmarkId == bookmarkId;
|
||||
other.imageURL == imageURL;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -88,8 +85,7 @@ class ActivityPlanModel {
|
|||
learningObjective.hashCode ^
|
||||
instructions.hashCode ^
|
||||
Object.hashAll(vocab) ^
|
||||
imageURL.hashCode ^
|
||||
bookmarkId.hashCode;
|
||||
imageURL.hashCode;
|
||||
}
|
||||
|
||||
class Vocab {
|
||||
|
|
|
|||
|
|
@ -11,11 +11,9 @@ class BookmarkedActivitiesRepo {
|
|||
/// returns the activity with a bookmarkId
|
||||
static Future<ActivityPlanModel> save(
|
||||
ActivityPlanModel activity,
|
||||
String bookmarkID,
|
||||
) async {
|
||||
activity.bookmarkId = bookmarkID;
|
||||
await _bookStorage.write(
|
||||
bookmarkID,
|
||||
activity.bookmarkId,
|
||||
activity.toJson(),
|
||||
);
|
||||
|
||||
|
|
@ -27,8 +25,7 @@ class BookmarkedActivitiesRepo {
|
|||
_bookStorage.remove(bookmarkId);
|
||||
|
||||
static bool isBookmarked(ActivityPlanModel activity) {
|
||||
return activity.bookmarkId != null &&
|
||||
_bookStorage.read(activity.bookmarkId!) != null;
|
||||
return _bookStorage.read(activity.bookmarkId) != null;
|
||||
}
|
||||
|
||||
static List<ActivityPlanModel> get() {
|
||||
|
|
|
|||
|
|
@ -52,13 +52,8 @@ class BookmarkedActivitiesListState extends State<BookmarkedActivitiesList> {
|
|||
activity.imageURL = url.toString();
|
||||
}
|
||||
|
||||
final uniqueID =
|
||||
"${activity.title.replaceAll(RegExp(r'\s+'), '-')}-${DateTime.now().millisecondsSinceEpoch}";
|
||||
|
||||
if (activity.bookmarkId != null) {
|
||||
await BookmarkedActivitiesRepo.remove(activity.bookmarkId!);
|
||||
}
|
||||
await BookmarkedActivitiesRepo.save(activity, uniqueID);
|
||||
await BookmarkedActivitiesRepo.remove(activity.bookmarkId);
|
||||
await BookmarkedActivitiesRepo.save(activity);
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -189,16 +189,11 @@ class ActivitySuggestionCard extends StatelessWidget {
|
|||
),
|
||||
onPressed: onPressed != null
|
||||
? () async {
|
||||
final uniqueID =
|
||||
"${activity.title.replaceAll(RegExp(r'\s+'), '-')}-${DateTime.now().millisecondsSinceEpoch}";
|
||||
await (isBookmarked
|
||||
? BookmarkedActivitiesRepo.remove(
|
||||
activity.bookmarkId!,
|
||||
activity.bookmarkId,
|
||||
)
|
||||
: BookmarkedActivitiesRepo.save(
|
||||
activity,
|
||||
uniqueID,
|
||||
));
|
||||
: BookmarkedActivitiesRepo.save(activity));
|
||||
onChange();
|
||||
}
|
||||
: null,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
|||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:shimmer/shimmer.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart';
|
||||
|
|
@ -48,6 +49,7 @@ class ActivitySuggestionsAreaState extends State<ActivitySuggestionsArea> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
bool _loading = true;
|
||||
bool get _isColumnMode => FluffyThemes.isColumnMode(context);
|
||||
|
||||
final List<ActivityPlanModel> _activityItems = [];
|
||||
|
|
@ -57,52 +59,72 @@ class ActivitySuggestionsAreaState extends State<ActivitySuggestionsArea> {
|
|||
double get cardWidth => _isColumnMode ? 225.0 : 150.0;
|
||||
|
||||
Future<void> _setActivityItems() async {
|
||||
final ActivityPlanRequest request = ActivityPlanRequest(
|
||||
topic: "",
|
||||
mode: "",
|
||||
objective: "",
|
||||
media: MediaEnum.nan,
|
||||
cefrLevel: LanguageLevelTypeEnum.a1,
|
||||
languageOfInstructions: LanguageKeys.defaultLanguage,
|
||||
targetLanguage:
|
||||
MatrixState.pangeaController.languageController.userL2?.langCode ??
|
||||
LanguageKeys.defaultLanguage,
|
||||
numberOfParticipants: 3,
|
||||
count: 5,
|
||||
);
|
||||
final resp = await ActivitySearchRepo.get(request);
|
||||
_activityItems.addAll(resp.activityPlans);
|
||||
if (mounted) setState(() {});
|
||||
try {
|
||||
final ActivityPlanRequest request = ActivityPlanRequest(
|
||||
topic: "",
|
||||
mode: "",
|
||||
objective: "",
|
||||
media: MediaEnum.nan,
|
||||
cefrLevel: LanguageLevelTypeEnum.a1,
|
||||
languageOfInstructions: LanguageKeys.defaultLanguage,
|
||||
targetLanguage:
|
||||
MatrixState.pangeaController.languageController.userL2?.langCode ??
|
||||
LanguageKeys.defaultLanguage,
|
||||
numberOfParticipants: 3,
|
||||
count: 5,
|
||||
);
|
||||
final resp = await ActivitySearchRepo.get(request);
|
||||
_activityItems.addAll(resp.activityPlans);
|
||||
} finally {
|
||||
if (mounted) setState(() => _loading = false);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<Widget> cards = _activityItems
|
||||
.map((activity) {
|
||||
return ActivitySuggestionCard(
|
||||
activity: activity,
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return ActivitySuggestionDialog(
|
||||
activity: activity,
|
||||
buttonText: L10n.of(context).inviteAndLaunch,
|
||||
room: widget.room,
|
||||
final theme = Theme.of(context);
|
||||
final List<Widget> cards = _loading
|
||||
? List.generate(5, (i) {
|
||||
return Shimmer.fromColors(
|
||||
baseColor: theme.colorScheme.primary.withAlpha(20),
|
||||
highlightColor: theme.colorScheme.primary.withAlpha(50),
|
||||
child: Container(
|
||||
height: cardHeight,
|
||||
width: cardWidth,
|
||||
margin: EdgeInsets.all(cardPadding),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(24.0),
|
||||
),
|
||||
),
|
||||
);
|
||||
})
|
||||
: _activityItems
|
||||
.map((activity) {
|
||||
return ActivitySuggestionCard(
|
||||
activity: activity,
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return ActivitySuggestionDialog(
|
||||
activity: activity,
|
||||
buttonText: L10n.of(context).inviteAndLaunch,
|
||||
room: widget.room,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
width: cardWidth,
|
||||
height: cardHeight,
|
||||
padding: cardPadding,
|
||||
onChange: () {
|
||||
if (mounted) setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
width: cardWidth,
|
||||
height: cardHeight,
|
||||
padding: cardPadding,
|
||||
onChange: () {
|
||||
if (mounted) setState(() {});
|
||||
},
|
||||
);
|
||||
})
|
||||
.cast<Widget>()
|
||||
.toList();
|
||||
})
|
||||
.cast<Widget>()
|
||||
.toList();
|
||||
|
||||
final scrollDirection = widget.scrollDirection ??
|
||||
(_isColumnMode ? Axis.horizontal : Axis.vertical);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue