Skip to content

Commit

Permalink
Merge branch 'dev' into course-overview-bug-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
GravityDarkLab authored Feb 2, 2024
2 parents d59f871 + a613313 commit 1f1f7c9
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 31 deletions.
1 change: 0 additions & 1 deletion lib/view_models/user_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ class UserViewModel extends StateNotifier<UserState> {
state = state.copyWith(isLoading: true);
try {
var semesters = await CourseHandler(_grpcHandler).fetchSemesters();
semesters.item1.add(semesters.item2);
state = state.copyWith(current: semesters.item2, isLoading: false);
state = state.copyWith(semesters: semesters.item1, isLoading: false);

Expand Down
3 changes: 0 additions & 3 deletions lib/views/components/filter_popup_menu_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ class FilterPopupMenuButton extends ConsumerWidget {

return PopupMenuButton<String>(
onSelected: (choice) {
// When an item is selected, update both providers to ensure they stay in sync
ref.read(userViewModelProvider.notifier).setSelectedSemester(choice);
ref.read(pinnedCourseViewModelProvider.notifier).setSelectedSemester(choice);
onClick(choice);
},
itemBuilder: (BuildContext context) {
Expand Down
1 change: 1 addition & 0 deletions lib/views/course_view/components/live_stream_section.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class LiveStreamSection extends StatelessWidget {
roomName: stream.item1.roomName,
roomNumber: stream.item1.roomCode,
path: imagePath,
isDownloaded: false,
courseId: course.id,
onTap: () {
Navigator.push(
Expand Down
56 changes: 45 additions & 11 deletions lib/views/course_view/components/small_stream_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:gocast_mobile/base/networking/api/gocast/api_v2.pb.dart';
import 'package:gocast_mobile/utils/constants.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
//import 'package:http/http.dart' as http;

class SmallStreamCard extends StatelessWidget {
final String title;
Expand Down Expand Up @@ -131,7 +132,7 @@ class SmallStreamCard extends StatelessWidget {
_buildCourseTitle(themeData.textTheme),
_buildCourseSubtitle(themeData.textTheme),
const SizedBox(height: 15),
_buildLocation(themeData),
if (!isDownloaded!) _buildLocation(themeData),
],
),
),
Expand Down Expand Up @@ -183,14 +184,25 @@ class SmallStreamCard extends StatelessWidget {
],
);
}

Widget _buildLocation(ThemeData themeData) {
if (roomNumber == null) return const SizedBox();
final isLocationEmpty =
(roomName?.isEmpty ?? true) && (roomNumber?.isEmpty ?? true);

return isLocationEmpty
? _buildInactiveLocation(themeData)
: _buildActiveLocation(themeData);
}

final Uri url = Uri.parse('https://nav.tum.de/room/$roomNumber');
Widget _buildActiveLocation(ThemeData themeData) {
// Determine the URL based on the availability of roomNumber
final Uri url = roomNumber?.isNotEmpty ?? false
? Uri.parse(
'https://nav.tum.de/room/$roomNumber') // Use roomNumber in URL if available
: Uri.parse(
'https://nav.tum.de/search?q=${Uri.encodeComponent(roomName ?? '')}'); // Fall back to search URL using roomName

return Align(
alignment: Alignment.centerRight, // Align to the right
alignment: Alignment.centerRight,
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
Expand All @@ -204,18 +216,19 @@ class SmallStreamCard extends StatelessWidget {
),
child: InkWell(
onTap: () async {
if (await canLaunchUrl(url)) {
await launchUrl(url);
} else {
throw 'Could not launch $url';
try {
if (await canLaunchUrl(url)) {
await launchUrl(url);
}
} catch (e) {
// Handle exceptions or errors here
}
},
child: const Row(
mainAxisSize: MainAxisSize.min,
// Constrain row size to its children
children: [
Icon(Icons.room, size: 24),
SizedBox(width: 8), // Spacing before the arrow icon
SizedBox(width: 8),
Icon(Icons.arrow_forward_ios, size: 16),
],
),
Expand All @@ -224,6 +237,27 @@ class SmallStreamCard extends StatelessWidget {
);
}

Widget _buildInactiveLocation(ThemeData themeData) {
return Align(
alignment: Alignment.centerRight,
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.withOpacity(0.4)),
borderRadius: BorderRadius.circular(5),
),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.room, size: 24, color: Colors.grey),
SizedBox(width: 8),
Icon(Icons.arrow_forward_ios, size: 16, color: Colors.grey),
],
),
),
);
}

Widget _buildCourseTumID() {
return Text(
tumID,
Expand Down
5 changes: 1 addition & 4 deletions lib/views/course_view/components/stream_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ class StreamCard extends ConsumerStatefulWidget {
}

class StreamCardState extends ConsumerState<StreamCard> {
String imageName =
'https://live.rbg.tum.de/thumb-fallback.png'; // Replace with your image URL

@override
void initState() {
super.initState();
Expand Down Expand Up @@ -103,7 +100,7 @@ class StreamCardState extends ConsumerState<StreamCard> {
AspectRatio(
aspectRatio: 16 / 9,
child: Image.network(
imageName,
widget.imageName,
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class CourseDetailState extends ConsumerState<CourseDetail> {
videoViewModelNotifier.updatedDisplayedStreams(temp);
isSearchInitialized = false;
} else {
displayedStreams = displayedStreams.where((stream) {
displayedStreams = temp.where((stream) {
return stream.item1.name.toLowerCase().contains(searchInput) ||
stream.item1.description.toLowerCase().contains(searchInput);
}).toList();
Expand All @@ -88,7 +88,7 @@ class CourseDetailState extends ConsumerState<CourseDetail> {
appBar: CustomSearchTopNavBarWithBackButton(
searchController: searchController,
onClick: _handleSortOptionSelected,
filterOptions: [AppLocalizations.of(context)!.newest_first, AppLocalizations.of(context)!.oldest_first],
filterOptions: const ['Newest First', 'Oldest First'],
),
body: RefreshIndicator(
onRefresh: () => _refreshStreams(widget.courseId),
Expand Down
17 changes: 12 additions & 5 deletions lib/views/course_view/courses_overview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:gocast_mobile/providers.dart';
import 'package:gocast_mobile/utils/section_kind.dart';
import 'package:gocast_mobile/utils/sort_utils.dart';
import 'package:gocast_mobile/views/components/base_view.dart';
import 'package:gocast_mobile/views/course_view/components/course_section.dart';
import 'package:gocast_mobile/views/course_view/components/live_stream_section.dart';
Expand Down Expand Up @@ -49,6 +50,12 @@ class CourseOverviewState extends ConsumerState<CourseOverview> {
}
final userCourses = ref.watch(userViewModelProvider).userCourses ?? [];
final publicCourses = ref.watch(userViewModelProvider).publicCourses ?? [];
final currentSemester =
ref.watch(userViewModelProvider).currentAsString ?? "All";
final userCoursesCurrent =
CourseUtils.filterCoursesBySemester(userCourses, currentSemester);
final publicCoursesCurrent =
CourseUtils.filterCoursesBySemester(publicCourses, currentSemester);
final liveStreams = ref.watch(videoViewModelProvider).liveStreams;
final liveStreamWithThumb =
ref.watch(videoViewModelProvider).liveStreamsWithThumb ?? [];
Expand Down Expand Up @@ -76,7 +83,7 @@ class CourseOverviewState extends ConsumerState<CourseOverview> {
child: LiveStreamSection(
ref: ref,
sectionTitle: AppLocalizations.of(context)!.live_now,
courses: (userCourses) + (publicCourses),
courses: (userCoursesCurrent) + (publicCoursesCurrent),
streams: liveStreamWithThumb,
),
),
Expand All @@ -88,15 +95,15 @@ class CourseOverviewState extends ConsumerState<CourseOverview> {
child: _buildSection(
AppLocalizations.of(context)!.my_courses,
SectionKind.myCourses,
userCourses,
userCoursesCurrent,
liveStreams,
),
),
Expanded(
child: _buildSection(
AppLocalizations.of(context)!.public_courses,
SectionKind.publicCourses,
publicCourses,
publicCoursesCurrent,
liveStreams,
),
),
Expand All @@ -106,13 +113,13 @@ class CourseOverviewState extends ConsumerState<CourseOverview> {
_buildSection(
AppLocalizations.of(context)!.my_courses,
SectionKind.myCourses,
userCourses,
userCoursesCurrent,
liveStreams,
),
_buildSection(
AppLocalizations.of(context)!.public_courses,
SectionKind.publicCourses,
publicCourses,
publicCoursesCurrent,
liveStreams,
),
],
Expand Down
5 changes: 4 additions & 1 deletion lib/views/course_view/list_courses_view/my_courses_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class MyCoursesState extends ConsumerState<MyCourses> {

void filterCoursesBySemester(String selectedSemester) {
var allUserCourses = ref.watch(userViewModelProvider).userCourses ?? [];
ref
.read(pinnedCourseViewModelProvider.notifier)
.setSelectedSemester(selectedSemester);
ref
.read(userViewModelProvider.notifier)
.updateSelectedSemester(selectedSemester, allUserCourses);
Expand All @@ -59,7 +62,7 @@ class MyCoursesState extends ConsumerState<MyCourses> {
userViewModelNotifier.updatedDisplayedCourses(temp);
isSearchInitialized = false;
} else {
displayedCourses = displayedCourses.where((course) {
displayedCourses = temp.where((course) {
return course.name.toLowerCase().contains(searchInput) ||
course.slug.toLowerCase().contains(searchInput);
}).toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class PublicCoursesState extends ConsumerState<PublicCourses> {
void _initializeCourses() {
final userViewModelNotifier = ref.read(userViewModelProvider.notifier);
Future.microtask(() async {
await userViewModelNotifier.fetchPublicCourses();
await userViewModelNotifier.fetchSemesters();
await userViewModelNotifier.fetchPublicCourses();
});
}

Expand All @@ -41,6 +41,9 @@ class PublicCoursesState extends ConsumerState<PublicCourses> {

void filterCoursesBySemester(String selectedSemester) {
var allUserCourses = ref.watch(userViewModelProvider).publicCourses ?? [];
ref
.read(pinnedCourseViewModelProvider.notifier)
.setSelectedSemester(selectedSemester);
ref
.read(userViewModelProvider.notifier)
.updateSelectedSemester(selectedSemester, allUserCourses);
Expand All @@ -60,7 +63,7 @@ class PublicCoursesState extends ConsumerState<PublicCourses> {
userViewModelNotifier.updatedDisplayedCourses(temp);
isSearchInitialized = false;
} else {
displayedCourses = displayedCourses.where((course) {
displayedCourses = temp.where((course) {
return course.name.toLowerCase().contains(searchInput) ||
course.slug.toLowerCase().contains(searchInput);
}).toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class PinnedCoursesState extends ConsumerState<PinnedCourses> {
}

void filterCoursesBySemester(String selectedSemester) {
ref
.read(userViewModelProvider.notifier)
.setSelectedSemester(selectedSemester);
var userPinned = ref.watch(pinnedCourseViewModelProvider).userPinned ?? [];
ref
.read(pinnedCourseViewModelProvider.notifier)
Expand All @@ -62,7 +65,7 @@ class PinnedCoursesState extends ConsumerState<PinnedCourses> {
pinnedViewModelNotifier.updatedDisplayedPinnedCourses(temp);
isSearchInitialized = false;
} else {
displayedCourses = displayedCourses.where((course) {
displayedCourses = temp.where((course) {
return course.name.toLowerCase().contains(searchInput) ||
course.slug.toLowerCase().contains(searchInput);
}).toList();
Expand Down
3 changes: 2 additions & 1 deletion lib/views/video_view/video_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ class VideoPlayerPageState extends ConsumerState<VideoPlayerPage> {
.read(courseViewModelProvider)
.course;
if (course != null) {
if (course.chatEnabled && course.vodChatEnabled && widget.stream.chatEnabled) {
if ((course.chatEnabled && widget.stream.chatEnabled) ||
(course.vodChatEnabled && widget.stream.chatEnabled)) {
setState(() {
_isChatActive = true;
_isPollActive = true;
Expand Down

0 comments on commit 1f1f7c9

Please sign in to comment.