implemented a comprehensive client-side demo mode triggered by a "demo@" username prefix, serving curated fixture data for all app modules
This commit is contained in:
@@ -12,9 +12,9 @@ class BreakerDataProvider {
|
||||
bool renew = true,
|
||||
void Function(Object)? onError,
|
||||
}) => resolveFromCache<GetBreakersResponse>(
|
||||
(onUpdate, onError) =>
|
||||
GetBreakersCache(renew: renew, onUpdate: onUpdate, onError: onError),
|
||||
onError: onError,
|
||||
operationName: 'getBreakers',
|
||||
);
|
||||
(onUpdate, onError) =>
|
||||
GetBreakersCache(renew: renew, onUpdate: onUpdate, onError: onError),
|
||||
onError: onError,
|
||||
operationName: 'getBreakers',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'dart:developer';
|
||||
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
|
||||
import '../../../../../api/demo/data/demo_capabilities.dart';
|
||||
import '../../../../../api/demo/demo_mode.dart';
|
||||
import '../../../../../api/marianumconnect/queries/get_capabilities/get_capabilities.dart';
|
||||
import 'capabilities_state.dart';
|
||||
|
||||
@@ -20,6 +22,10 @@ class CapabilitiesCubit extends HydratedCubit<CapabilitiesState> {
|
||||
/// state is marked `loaded` — a failed fetch never silently grants a
|
||||
/// capability, and an offline launch keeps whatever was cached.
|
||||
Future<void> load() async {
|
||||
if (DemoMode.active) {
|
||||
emit(DemoCapabilities.state());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final response = await GetCapabilities().run();
|
||||
emit(
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import '../../../../../api/demo/data/demo_talk.dart';
|
||||
import '../../../../../api/demo/demo_mode.dart';
|
||||
import '../../../../../api/marianumcloud/talk/chat/get_chat_cache.dart';
|
||||
import '../../../../../api/marianumcloud/talk/chat/get_chat_response.dart';
|
||||
|
||||
@@ -8,6 +10,12 @@ class ChatDataProvider {
|
||||
void Function(GetChatResponse data)? onNetworkData,
|
||||
void Function(Object)? onError,
|
||||
}) async {
|
||||
if (DemoMode.active) {
|
||||
final data = DemoTalk.chat(token);
|
||||
onCacheData?.call(data);
|
||||
onNetworkData?.call(data);
|
||||
return;
|
||||
}
|
||||
final cache = GetChatCache(
|
||||
chatToken: token,
|
||||
onCacheData: onCacheData,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import '../../../../../api/demo/data/demo_talk.dart';
|
||||
import '../../../../../api/demo/demo_mode.dart';
|
||||
import '../../../../../api/marianumcloud/talk/create_room/create_room.dart';
|
||||
import '../../../../../api/marianumcloud/talk/create_room/create_room_params.dart';
|
||||
import '../../../../../api/marianumcloud/talk/room/get_room_cache.dart';
|
||||
@@ -8,13 +10,18 @@ class ChatListDataProvider {
|
||||
Future<GetRoomResponse> getRooms({
|
||||
void Function(Object)? onError,
|
||||
bool renew = false,
|
||||
}) => resolveFromCache<GetRoomResponse>(
|
||||
(onUpdate, onError) =>
|
||||
GetRoomCache(renew: renew, onUpdate: onUpdate, onError: onError),
|
||||
onError: onError,
|
||||
operationName: 'getRooms',
|
||||
);
|
||||
}) {
|
||||
if (DemoMode.active) return Future.value(DemoTalk.rooms());
|
||||
return resolveFromCache<GetRoomResponse>(
|
||||
(onUpdate, onError) =>
|
||||
GetRoomCache(renew: renew, onUpdate: onUpdate, onError: onError),
|
||||
onError: onError,
|
||||
operationName: 'getRooms',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> createDirectRoom(String invite) =>
|
||||
CreateRoom(CreateRoomParams(roomType: 1, invite: invite)).run();
|
||||
Future<void> createDirectRoom(String invite) {
|
||||
if (DemoMode.active) return Future.value();
|
||||
return CreateRoom(CreateRoomParams(roomType: 1, invite: invite)).run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:nextcloud/nextcloud.dart';
|
||||
|
||||
import '../../../../../api/demo/data/demo_files.dart';
|
||||
import '../../../../../api/demo/demo_mode.dart';
|
||||
import '../../../../../api/marianumcloud/webdav/queries/list_files/list_files_cache.dart';
|
||||
import '../../../../../api/marianumcloud/webdav/queries/list_files/list_files_response.dart';
|
||||
import '../../../../../api/marianumcloud/webdav/webdav_api.dart';
|
||||
@@ -19,20 +21,24 @@ class FilesDataProvider {
|
||||
void Function(Object)? onError,
|
||||
bool renew = false,
|
||||
void Function(int nextAttempt, int maxAttempts)? onRetry,
|
||||
}) => resolveFromCache<ListFilesResponse>(
|
||||
(onUpdate, onError) => ListFilesCache(
|
||||
path: path,
|
||||
onUpdate: onUpdate,
|
||||
onCacheData: onCacheData,
|
||||
}) {
|
||||
if (DemoMode.active) return Future.value(DemoFiles.listing(path));
|
||||
return resolveFromCache<ListFilesResponse>(
|
||||
(onUpdate, onError) => ListFilesCache(
|
||||
path: path,
|
||||
onUpdate: onUpdate,
|
||||
onCacheData: onCacheData,
|
||||
onError: onError,
|
||||
renew: renew,
|
||||
onRetry: onRetry,
|
||||
),
|
||||
onError: onError,
|
||||
renew: renew,
|
||||
onRetry: onRetry,
|
||||
),
|
||||
onError: onError,
|
||||
operationName: 'listFiles',
|
||||
);
|
||||
operationName: 'listFiles',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> createFolder(String fullPath) async {
|
||||
if (DemoMode.active) return;
|
||||
final webdav = await WebdavApi.webdav;
|
||||
await webdav.mkcol(PathUri.parse(fullPath));
|
||||
}
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
|
||||
import '../../../../../api/demo/demo_mode.dart';
|
||||
import 'grade_averages_event.dart';
|
||||
import 'grade_averages_state.dart';
|
||||
|
||||
class GradeAveragesBloc
|
||||
extends HydratedBloc<GradeAveragesEvent, GradeAveragesState> {
|
||||
// Seeded with a realistic spread in demo mode (average 2.0); empty otherwise.
|
||||
static const List<int> _demoGrades = [1, 2, 2, 2, 3, 2, 1, 3, 2, 2];
|
||||
|
||||
GradeAveragesBloc()
|
||||
: super(
|
||||
const GradeAveragesState(
|
||||
GradeAveragesState(
|
||||
gradingSystem: GradeAveragesGradingSystem.middleSchool,
|
||||
grades: [],
|
||||
grades: DemoMode.active ? _demoGrades : const [],
|
||||
),
|
||||
) {
|
||||
on<GradingSystemChanged>((event, emit) {
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import '../../../../../api/demo/data/demo_marianum_dates.dart';
|
||||
import '../../../../../api/demo/demo_mode.dart';
|
||||
import '../../../infrastructure/repository/repository.dart';
|
||||
import '../bloc/marianum_dates_state.dart';
|
||||
import '../data_provider/marianum_dates_get_events.dart';
|
||||
|
||||
class MarianumDatesRepository extends Repository<MarianumDatesState> {
|
||||
Future<List<MarianumDate>> getEvents() => MarianumDatesGetEvents().run();
|
||||
Future<List<MarianumDate>> getEvents() {
|
||||
if (DemoMode.active) return Future.value(DemoMarianumDates.events());
|
||||
return MarianumDatesGetEvents().run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import '../../../../../api/demo/data/demo_marianum_message.dart';
|
||||
import '../../../../../api/demo/demo_mode.dart';
|
||||
import '../../../infrastructure/repository/repository.dart';
|
||||
import '../bloc/marianum_message_state.dart';
|
||||
import '../data_provider/marianum_message_get_messages.dart';
|
||||
|
||||
class MarianumMessageRepository extends Repository<MarianumMessageState> {
|
||||
Future<MarianumMessageList> getMessages() =>
|
||||
MarianumMessageGetMessages().run();
|
||||
Future<MarianumMessageList> getMessages() {
|
||||
if (DemoMode.active) return Future.value(DemoMarianumMessage.list());
|
||||
return MarianumMessageGetMessages().run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'dart:developer';
|
||||
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
|
||||
import '../../../../../api/demo/data/demo_capabilities.dart';
|
||||
import '../../../../../api/demo/demo_mode.dart';
|
||||
import '../../../../../api/marianumcloud/capabilities/get_nextcloud_capabilities.dart';
|
||||
import 'nextcloud_capabilities_state.dart';
|
||||
|
||||
@@ -57,6 +59,10 @@ class NextcloudCapabilitiesCubit
|
||||
/// Refreshes capabilities from the server. On any failure the previously
|
||||
/// hydrated flags are kept but the state is marked `loaded`.
|
||||
Future<void> load() async {
|
||||
if (DemoMode.active) {
|
||||
emit(DemoNextcloudCapabilities.state());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final caps = await GetNextcloudCapabilities().run();
|
||||
emit(
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import '../../../../../api/demo/data/demo_timetable.dart';
|
||||
import '../../../../../api/demo/demo_mode.dart';
|
||||
import '../../../../../api/marianumconnect/queries/timetable_get_holidays/timetable_get_holidays.dart';
|
||||
import '../../../../../api/marianumconnect/queries/timetable_get_holidays/timetable_get_holidays_response.dart';
|
||||
import '../../../../../api/marianumconnect/queries/timetable_get_rooms/timetable_get_rooms.dart';
|
||||
@@ -95,27 +97,36 @@ class TimetableDataProvider {
|
||||
Future<GetCustomTimetableEventResponse> getCustomEvents({
|
||||
bool renew = false,
|
||||
void Function(Object)? onError,
|
||||
}) => resolveFromCache<GetCustomTimetableEventResponse>(
|
||||
}) {
|
||||
if (DemoMode.active) return Future.value(DemoTimetable.customEvents());
|
||||
return resolveFromCache<GetCustomTimetableEventResponse>(
|
||||
(onUpdate, onError) => GetCustomTimetableEventCache(
|
||||
GetCustomTimetableEventParams(AccountData().getUserSecret()),
|
||||
renew: renew,
|
||||
onUpdate: onUpdate,
|
||||
onError: onError,
|
||||
),
|
||||
onError: onError,
|
||||
operationName: 'getCustomEvents',
|
||||
);
|
||||
onError: onError,
|
||||
operationName: 'getCustomEvents',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addCustomEvent(CustomTimetableEvent event) =>
|
||||
AddCustomTimetableEvent(
|
||||
AddCustomTimetableEventParams(AccountData().getUserSecret(), event),
|
||||
).run();
|
||||
Future<void> addCustomEvent(CustomTimetableEvent event) {
|
||||
if (DemoMode.active) return Future.value();
|
||||
return AddCustomTimetableEvent(
|
||||
AddCustomTimetableEventParams(AccountData().getUserSecret(), event),
|
||||
).run();
|
||||
}
|
||||
|
||||
Future<void> updateCustomEvent(String id, CustomTimetableEvent event) =>
|
||||
UpdateCustomTimetableEvent(
|
||||
UpdateCustomTimetableEventParams(id, event),
|
||||
).run();
|
||||
Future<void> updateCustomEvent(String id, CustomTimetableEvent event) {
|
||||
if (DemoMode.active) return Future.value();
|
||||
return UpdateCustomTimetableEvent(
|
||||
UpdateCustomTimetableEventParams(id, event),
|
||||
).run();
|
||||
}
|
||||
|
||||
Future<void> removeCustomEvent(String id) =>
|
||||
RemoveCustomTimetableEvent(RemoveCustomTimetableEventParams(id)).run();
|
||||
Future<void> removeCustomEvent(String id) {
|
||||
if (DemoMode.active) return Future.value();
|
||||
return RemoveCustomTimetableEvent(RemoveCustomTimetableEventParams(id)).run();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user