Skip to content

Commit

Permalink
Merge branch 'main' of github.com:ia-toki/bebras-pandai into feature-…
Browse files Browse the repository at this point in the history
…admin-task
  • Loading branch information
gmochid committed Nov 25, 2023
2 parents 373f883 + 72d2cfa commit c971e25
Show file tree
Hide file tree
Showing 14 changed files with 218 additions and 23 deletions.
5 changes: 4 additions & 1 deletion app/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

<application
android:label="bebras_pandai"
android:label="Bebras Pandai"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true">
Expand Down Expand Up @@ -34,5 +34,8 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/notification_icon" />
</application>
</manifest>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions app/lib/api/firebase_api.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

import '../services/firebase_service.dart';
import '../services/router_service.dart';

class FirebaseApi {
final _firebaseMessaging = FirebaseMessaging.instance;
final currentUser = FirebaseService.auth().currentUser;

void handleMessage(RemoteMessage? message) {
if (message == null) return;

router.push('/main');
}

Future<dynamic> initPushNotfications() async {
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);

await FirebaseMessaging.instance.getInitialMessage().then(handleMessage);
FirebaseMessaging.onMessageOpenedApp.listen(handleMessage);
FirebaseMessaging.onBackgroundMessage(handleBackgroundMessage);
}

Future<void> initNotifications() async {
await _firebaseMessaging.requestPermission();

FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) {
Map<String, dynamic> deviceToken = {
'fcm_token': fcmToken,
'fcm_timestamp': FieldValue.serverTimestamp(),
};

// Reference to the Firestore collection
CollectionReference<Map<String, dynamic>> fcmTokensCollection =
FirebaseFirestore.instance.collection('registered_user');

// Set the device token in Firestore
fcmTokensCollection.doc(currentUser!.uid).update(deviceToken);
}).onError((err) {
// Error getting token.
});

final fCMToken = await _firebaseMessaging.getToken();
print('Token: $fCMToken');
await initPushNotfications();
}
}
30 changes: 30 additions & 0 deletions app/lib/core/bases/widgets/atoms/html_cached_image.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';

class HtmlWithCachedImages extends StatelessWidget {
final String data;

const HtmlWithCachedImages({
required this.data,
super.key,
});

@override
Widget build(BuildContext context) {
return Html(
data: data,
extensions: <HtmlExtension>[
ImageExtension(
builder: (ExtensionContext extensionContext) {
final element = extensionContext.styledElement!;
return CachedNetworkImage(
imageUrl: element.attributes['src']!,
fit: BoxFit.cover,
);
},
),
],
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ class _RegisterPageState extends State<RegisterPage> {
(val) {
return state.province.error;
},
state.province.value,
state.province.value.isNotEmpty
? state.province.value
: 'Provinsi',
),
BiroBebrasDropdown(
'Bebras Biro',
Expand All @@ -176,7 +178,9 @@ class _RegisterPageState extends State<RegisterPage> {
(val) {
return state.bebrasBiro.error;
},
state.bebrasBiro.value,
state.bebrasBiro.value.isNotEmpty
? state.bebrasBiro.value
: 'Bebras Biro',
),
const SizedBox(height: 20),
BlocConsumer<UserRegisterBloc, RegisterFormState>(
Expand Down
8 changes: 4 additions & 4 deletions app/lib/features/main/presentation/pages/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ class _HomePageState extends State<HomePage> {
style: FontTheme.blackTitle(),
children: <TextSpan>[
TextSpan(
text: toBeginningOfSentenceCase(
'${state.user.name}!',
),
),
text: toBeginningOfSentenceCase(
'${state.user.name}!',
),
style: FontTheme.blackTitleBold()),
],
),
);
Expand Down
13 changes: 5 additions & 8 deletions app/lib/features/main/presentation/pages/setting_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ class _SettingPageState extends State<SettingPage> {
if (state is HomeSuccess && state.user.isAdmin) {
return Column(
children: [
const SizedBox(
height: 130,
SizedBox(
height: MediaQuery.of(context).size.height - 625,
),
Button(
onTap: () {
Expand All @@ -101,19 +101,16 @@ class _SettingPageState extends State<SettingPage> {
text: 'Lihat Bebras Task',
),
const SizedBox(
height: 20,
height: 25,
),
],
);
}
return const SizedBox(
height: 200,
return SizedBox(
height: MediaQuery.of(context).size.height - 695,
);
},
),
SizedBox(
height: MediaQuery.of(context).size.height - 695,
),
Button(
onTap: () async {
await FirebaseAuth.instance.signOut();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_html/flutter_html.dart';

import '../../../../core/bases/enum/button_type.dart';
import '../../../../core/bases/widgets/atoms/button.dart';
import '../../../../core/bases/widgets/atoms/html_cached_image.dart';
import '../../../../core/theme/font_theme.dart';
import '../../../authentication/register/presentation/widgets/custom_text_field.dart';
import '../bloc/quiz_exercise_cubit.dart';
Expand Down Expand Up @@ -44,7 +44,7 @@ class TaskDialog extends StatelessWidget {
width: 400,
height: 200,
child: SingleChildScrollView(
child: Html(data: task.question.content),
child: HtmlWithCachedImages(data: task.question.content),
),
),
if (!preview)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// ignore_for_file: lines_longer_than_80_chars

import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';

import '../../../../core/bases/enum/button_type.dart';
import '../../../../core/bases/widgets/atoms/button.dart';
import '../../../../core/bases/widgets/atoms/html_cached_image.dart';
import '../../../../core/constants/assets.dart';
import '../../../../core/theme/font_theme.dart';
import '../model/quiz_exercise.dart';
Expand Down Expand Up @@ -80,7 +80,7 @@ class TaskView extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(border: Border.all()),
child: SingleChildScrollView(
child: Html(
child: HtmlWithCachedImages(
// ignore: prefer_adjacent_string_concatenation
data: '<h3>Deskripsi</h3>${task.description.content}' +
'<h3>Pertanyaan</h3>${task.question.content}',
Expand Down
2 changes: 2 additions & 0 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

import 'api/firebase_api.dart';
import 'app.dart';
import 'services/di.dart';
import 'services/firebase_service.dart';
Expand All @@ -10,5 +11,6 @@ Future<void> main() async {
await dotenv.load();
configureDependencies();
await FirebaseService.initialize();
await FirebaseApi().initNotifications();
runApp(const App());
}
6 changes: 6 additions & 0 deletions app/lib/services/firebase_service.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

import '../firebase_options.dart';
import 'app_logger.dart';

Future<void> handleBackgroundMessage(RemoteMessage message) async {
print('Title: ${message.notification?.title}');
}

class FirebaseService {
static late FirebaseApp app;

static Future<void> initialize() async {
app = await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
Expand Down
2 changes: 2 additions & 0 deletions app/macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Foundation
import cloud_firestore
import firebase_auth
import firebase_core
import firebase_messaging
import firebase_storage
import flutter_local_notifications
import geolocator_apple
Expand All @@ -20,6 +21,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin"))
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
FLTFirebaseStoragePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseStoragePlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
Expand Down
Loading

0 comments on commit c971e25

Please sign in to comment.