blob: a13f9c4df849067c3a5763e939f4162314d1416f [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:get_it/get_it.dart';
import 'package:playground_components/playground_components.dart';
import '../auth/notifier.dart';
import '../enums/snippet_type.dart';
import '../enums/unit_completion.dart';
import '../models/unit_progress.dart';
import '../repositories/client/client.dart';
import '../repositories/models/get_user_progress_response.dart';
import '../repositories/user_progress/abstract.dart';
import '../repositories/user_progress/cloud.dart';
import '../repositories/user_progress/hive.dart';
import '../state.dart';
class UnitProgressCache extends ChangeNotifier {
final _cloudUserProgressRepository = CloudUserProgressRepository(
client: GetIt.instance.get<TobClient>(),
);
final _localStorageUserProgressRepository = HiveUserProgressRepository();
AbstractUserProgressRepository _getUserProgressRepository() {
if (isAuthenticated) {
return _cloudUserProgressRepository;
}
return _localStorageUserProgressRepository;
}
Future<GetUserProgressResponse?>? _future;
var _unitProgress = <UnitProgressModel>[];
final _unitProgressByUnitId = <String, UnitProgressModel>{};
final _completedUnitIds = <String>{};
final _updatingUnitIds = <String>{};
bool get isAuthenticated =>
GetIt.instance.get<AuthNotifier>().isAuthenticated;
Future<void> loadUnitProgress(Sdk sdk) async {
_future = _getUserProgressRepository().getUserProgress(sdk);
final result = await _future;
_unitProgressByUnitId.clear();
if (result != null) {
_unitProgress = result.units;
for (final unitProgress in _unitProgress) {
_unitProgressByUnitId[unitProgress.id] = unitProgress;
}
} else {
_unitProgress = [];
}
notifyListeners();
}
List<UnitProgressModel> _getUnitProgress() {
if (_future == null) {
unawaited(loadUnitProgress(GetIt.instance.get<AppNotifier>().sdk));
}
return _unitProgress;
}
// Completion
Future<void> completeUnit(String sdkId, String unitId) async {
try {
_addUpdatingUnitId(unitId);
await _getUserProgressRepository().completeUnit(sdkId, unitId);
} finally {
await loadUnitProgress(GetIt.instance.get<AppNotifier>().sdk);
_clearUpdatingUnitId(unitId);
}
}
Set<String> getCompletedUnits() {
_completedUnitIds.clear();
for (final unitProgress in _getUnitProgress()) {
if (unitProgress.isCompleted) {
_completedUnitIds.add(unitProgress.id);
}
}
return _completedUnitIds;
}
void _addUpdatingUnitId(String unitId) {
_updatingUnitIds.add(unitId);
notifyListeners();
}
void _clearUpdatingUnitId(String unitId) {
_updatingUnitIds.remove(unitId);
notifyListeners();
}
bool canCompleteUnit(String? unitId) {
if (unitId == null) {
return false;
}
return _getUnitCompletion(unitId) == UnitCompletion.uncompleted;
}
bool isUnitCompleted(String? unitId) {
return getCompletedUnits().contains(unitId);
}
UnitCompletion _getUnitCompletion(String unitId) {
final authNotifier = GetIt.instance.get<AuthNotifier>();
if (!authNotifier.isAuthenticated) {
return UnitCompletion.unauthenticated;
}
if (_updatingUnitIds.contains(unitId)) {
return UnitCompletion.updating;
}
if (isUnitCompleted(unitId)) {
return UnitCompletion.completed;
}
return UnitCompletion.uncompleted;
}
// Snippet
bool hasSavedSnippet(String? unitId) {
return _unitProgressByUnitId[unitId]?.userSnippetId != null;
}
Future<void> saveSnippet({
required Sdk sdk,
required List<SnippetFile> snippetFiles,
required SnippetType snippetType,
required String unitId,
}) async {
await _getUserProgressRepository().saveUnitSnippet(
sdk: sdk,
snippetFiles: snippetFiles,
snippetType: snippetType,
unitId: unitId,
);
}
Future<ExampleLoadingDescriptor> getSavedDescriptor({
required Sdk sdk,
required String unitId,
}) async {
return _getUserProgressRepository().getSavedDescriptor(
sdk: sdk,
unitId: unitId,
);
}
Future<void> deleteUserProgress() async {
await Future.wait([
_localStorageUserProgressRepository.deleteUserProgress(),
_cloudUserProgressRepository.deleteUserProgress(),
]);
}
}