woowww josssjissss

This commit is contained in:
kleponijo 2026-04-14 14:00:25 +07:00
parent 1239b39e30
commit adaeff826f
21 changed files with 256 additions and 451 deletions

BIN
images/windy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -24,6 +24,7 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
await _userRepository.signInWithGoogle(); await _userRepository.signInWithGoogle();
} catch (e) { } catch (e) {
emit(SignInFailure()); emit(SignInFailure());
emit(SignInInitial());
} }
}); });

View File

@ -20,15 +20,5 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
emit(SignUpFailure(e.toString())); emit(SignUpFailure(e.toString()));
} }
}); });
on<GoogleSignInRequired>((event, emit) async {
emit(SignUpProcess());
try {
await _userRepository.signInWithGoogle();
emit(SignUpSuccess());
} catch (e) {
emit(SignUpFailure(e.toString()));
}
});
} }
} }

View File

@ -25,19 +25,20 @@ class _SignInScreenState extends State<SignInScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocListener<SignInBloc, SignInState>( return BlocListener<SignInBloc, SignInState>(
listener: (context, state) { listener: (context, state) {
if (state is SignInSuccess) { if (state is SignInProcess) {
setState(() {
signInRequired = false;
});
} else if (state is SignInProcess) {
setState(() { setState(() {
signInRequired = true; signInRequired = true;
}); });
} else if (state is SignInFailure) { } else {
setState(() { setState(() {
signInRequired = false; signInRequired = false;
_errorMsg = 'Invalid email or password';
}); });
if (state is SignInFailure) {
setState(() {
// PERUBAHAN: Pesan error lebih umum karena Google gagal belum tentu soal password
_errorMsg = 'Sign in failed. Please try again.';
});
}
} }
}, },
child: Form( child: Form(

View File

@ -3,10 +3,13 @@ import 'package:user_repository/user_repository.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../components/my_text_field.dart'; import '../../../components/my_text_field.dart';
import '../blocs/sign_up_bloc/sign_up_bloc.dart'; import '../blocs/sign_up_bloc/sign_up_bloc.dart' as signUp;
// import '../../../blocs/authentication_bloc/authentication_bloc.dart';
import '../blocs/sign_in_bloc/sign_in_bloc.dart' as signIn;
class SignUpScreen extends StatefulWidget { class SignUpScreen extends StatefulWidget {
const SignUpScreen({super.key}); final VoidCallback? onSignInTap;
const SignUpScreen({super.key, this.onSignInTap});
@override @override
State<SignUpScreen> createState() => _SignUpScreenState(); State<SignUpScreen> createState() => _SignUpScreenState();
@ -30,18 +33,26 @@ class _SignUpScreenState extends State<SignUpScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocListener<SignUpBloc, SignUpState>( return BlocListener<signUp.SignUpBloc, signUp.SignUpState>(
listener: (context, state) { listener: (context, state) {
if (state is SignUpSuccess) { if (state is signUp.SignUpProcess) {
setState(() {
signUpRequired = false;
});
} else if (state is SignUpProcess) {
setState(() { setState(() {
signUpRequired = true; signUpRequired = true;
}); });
} else if (state is SignUpFailure) { } else if (state is signUp.SignUpFailure) {
return; setState(() {
signUpRequired = false; // Matikan loading!
});
// Tampilkan pesan error lewat Snackbar biar user tahu kenapa gagal
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.message ?? 'An error ocurred'),
backgroundColor: Colors.red),
);
} else if (state is signUp.SignUpSuccess) {
setState(() {
signUpRequired = false;
});
} }
}, },
child: Form( child: Form(
@ -181,10 +192,13 @@ class _SignUpScreenState extends State<SignUpScreen> {
const SizedBox(height: 18), const SizedBox(height: 18),
/// == Sign Up == ///
// Button // Button
!signUpRequired !signUpRequired
? SizedBox( ? Center(
width: MediaQuery.of(context).size.width * 0.92, child: SizedBox(
width:
MediaQuery.of(context).size.width * 0.5,
child: ElevatedButton( child: ElevatedButton(
onPressed: () { onPressed: () {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
@ -193,8 +207,8 @@ class _SignUpScreenState extends State<SignUpScreen> {
myUser.name = nameController.text; myUser.name = nameController.text;
setState(() { setState(() {
context.read<SignUpBloc>().add( context.read<signUp.SignUpBloc>().add(
SignUpRequired( signUp.SignUpRequired(
myUser, myUser,
passwordController.text, passwordController.text,
), ),
@ -202,22 +216,26 @@ class _SignUpScreenState extends State<SignUpScreen> {
}); });
} }
}, },
style: ElevatedButton.styleFrom( style: TextButton.styleFrom(
backgroundColor: Colors.black87, backgroundColor:
Theme.of(context).colorScheme.primary,
foregroundColor: Colors.white, foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
vertical: 16),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(60),
), ),
), ),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 25, vertical: 5),
child: const Text( child: const Text(
'Daftar', 'Sign Up',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
), ),
), ),
),
),
) )
: const CircularProgressIndicator(), : const CircularProgressIndicator(),
@ -225,39 +243,7 @@ class _SignUpScreenState extends State<SignUpScreen> {
Center( Center(
child: Text('Atau'), child: Text('Atau'),
), ),
const SizedBox(height: 12),
SizedBox(
width: MediaQuery.of(context).size.width * 0.92,
child: TextButton.icon(
onPressed: () {
context
.read<SignUpBloc>()
.add(GoogleSignInRequired());
},
icon: SizedBox(
height: 20,
width: 20,
child: Image.asset(
'images/google-icon-logo.png',
fit: BoxFit.contain,
),
),
label: const Text(
'Sign In With Google',
style: TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w600),
),
style: TextButton.styleFrom(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: const BorderSide(color: Colors.grey)),
padding: const EdgeInsets.symmetric(vertical: 16),
),
),
),
const SizedBox(height: 12), const SizedBox(height: 12),
Center( Center(
child: Row( child: Row(
@ -266,9 +252,12 @@ class _SignUpScreenState extends State<SignUpScreen> {
const Text('Sudah punya akun? '), const Text('Sudah punya akun? '),
TextButton( TextButton(
onPressed: () { onPressed: () {
Navigator.of(context).pop(); widget.onSignInTap?.call();
}, },
child: const Text('Login di sini'), child: const Text(
'Login di sini',
style: TextStyle(fontWeight: FontWeight.bold),
),
) )
], ],
), ),

View File

@ -13,20 +13,16 @@ class WelcomeScreen extends StatefulWidget {
State<WelcomeScreen> createState() => _WelcomeScreenState(); State<WelcomeScreen> createState() => _WelcomeScreenState();
} }
class _WelcomeScreenState extends State<WelcomeScreen> with TickerProviderStateMixin { class _WelcomeScreenState extends State<WelcomeScreen>
with TickerProviderStateMixin {
late TabController tabController; late TabController tabController;
@override @override
void initState() { void initState() {
tabController = TabController( tabController = TabController(initialIndex: 0, length: 2, vsync: this);
initialIndex: 0,
length: 2,
vsync: this
);
super.initState(); super.initState();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -46,8 +42,12 @@ class _WelcomeScreenState extends State<WelcomeScreen> with TickerProviderStateM
padding: const EdgeInsets.symmetric(horizontal: 50.0), padding: const EdgeInsets.symmetric(horizontal: 50.0),
child: TabBar( child: TabBar(
controller: tabController, controller: tabController,
unselectedLabelColor: Theme.of(context).colorScheme.onBackground.withOpacity(0.5), unselectedLabelColor: Theme.of(context)
labelColor: Theme.of(context).colorScheme.onBackground, .colorScheme
.onBackground
.withOpacity(0.5),
labelColor:
Theme.of(context).colorScheme.onBackground,
tabs: const [ tabs: const [
Padding( Padding(
padding: EdgeInsets.all(12.0), padding: EdgeInsets.all(12.0),
@ -75,20 +75,22 @@ class _WelcomeScreenState extends State<WelcomeScreen> with TickerProviderStateM
controller: tabController, controller: tabController,
children: [ children: [
BlocProvider<SignInBloc>( BlocProvider<SignInBloc>(
create: (context) => SignInBloc( create: (context) => SignInBloc(context
context.read<AuthenticationBloc>().userRepository .read<AuthenticationBloc>()
), .userRepository),
child: const SignInScreen(), child: const SignInScreen(),
), ),
BlocProvider<SignUpBloc>( BlocProvider<SignUpBloc>(
create: (context) => SignUpBloc( create: (context) => SignUpBloc(context
context.read<AuthenticationBloc>().userRepository .read<AuthenticationBloc>()
), .userRepository),
child: const SignUpScreen(), child: SignUpScreen(onSignInTap: () {
tabController.animateTo(
0); // Ini yang bikin dia pindah ke tab Login
}),
), ),
], ],
) ))
)
], ],
), ),
), ),

View File

@ -35,7 +35,11 @@ class MainDrawer extends StatelessWidget {
// Daftar Menu // Daftar Menu
ListTile( ListTile(
leading: const Icon(Icons.speed), leading: Image.asset(
'images/windy.png',
height: 20,
width: 20,
),
title: const Text("Wind Speed"), title: const Text("Wind Speed"),
onTap: () { onTap: () {
// Navigasi ke Wind Speed // Navigasi ke Wind Speed
@ -52,7 +56,7 @@ class MainDrawer extends StatelessWidget {
height: 20, height: 20,
width: 20, width: 20,
), ),
title: const Text("Udara"), title: const Text("Tekanan Udara"),
onTap: () {}, onTap: () {},
), ),
const Spacer(), // Dorong menu logout ke paling bawah const Spacer(), // Dorong menu logout ke paling bawah

View File

@ -3,7 +3,7 @@ import 'package:fl_chart/fl_chart.dart';
import 'package:firebase_database/firebase_database.dart'; import 'package:firebase_database/firebase_database.dart';
import 'dart:async'; import 'dart:async';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'shared/widgets/monitoring_shared.dart'; import '../../shared/widgets/monitoring_shared.dart';
/// EVAPORASI MONITORING SCREEN /// EVAPORASI MONITORING SCREEN
class EvaporasiMonitoringScreen extends StatefulWidget { class EvaporasiMonitoringScreen extends StatefulWidget {

View File

@ -2,34 +2,44 @@ import 'dart:async';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:monitoring_repository/monitoring_repository.dart'; import 'package:monitoring_repository/monitoring_repository.dart';
import 'package:bloc_concurrency/bloc_concurrency.dart';
part 'wind_speed_event.dart'; part 'wind_speed_event.dart';
part 'wind_speed_state.dart'; part 'wind_speed_state.dart';
class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> { class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
final MonitoringRepository _repository; final MonitoringRepository _repository;
StreamSubscription? _subscription;
WindSpeedBloc({required MonitoringRepository repository}) WindSpeedBloc({required MonitoringRepository repository})
: _repository = repository, : _repository = repository,
super(const WindSpeedState()) { super(const WindSpeedState()) {
// Handler saat aplikasi minta mulai monitoring // Handler saat aplikasi minta mulai monitoring
on<WatchWindSpeedStarted>((event, emit) { on<WatchWindSpeedStarted>(
_subscription?.cancel(); (event, emit) async {
_subscription = _repository emit(state.copyWith(isLoading: true));
.getSensorStream(
'anemometer/realtime', (json) => MyWindSpeed.fromJson(json))
.listen((data) => add(_WindSpeedUpdated(data)));
});
// Handler saat ada data baru masuk (Pindahan logika dari Screen) await emit.forEach<MyWindSpeed>(
on<_WindSpeedUpdated>((event, emit) { _repository.getSensorStream(
// Di sini kamu bisa tambahkan logika hitung rata-rata/grafik harian 'anemometer/realtime', (json) => MyWindSpeed.fromJson(json)),
emit(state.copyWith( onData: (data) {
currentSpeed: event.data.speed, // Mengambil list lama dan menambah data baru untuk grafik
final updatedSpeeds = List<double>.from(state.dailySpeeds)
..add(data.speed);
// Batasi jumlah data di grafik (misal cuma simpan 20 data terakhir agar tidak berat)
if (updatedSpeeds.length > 20) {
updatedSpeeds.removeAt(0);
}
return state.copyWith(
currentSpeed: data.speed,
dailySpeeds: updatedSpeeds, // Update list grafik
isLoading: false, isLoading: false,
)); );
}); },
onError: (error, stackTrace) => state.copyWith(isLoading: false),
); // emit forEach
},
transformer: restartable(),
);
on<WindSpeedPeriodChanged>((event, emit) { on<WindSpeedPeriodChanged>((event, emit) {
emit(state.copyWith(selectedPeriod: event.period)); emit(state.copyWith(selectedPeriod: event.period));
@ -38,7 +48,6 @@ class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
@override @override
Future<void> close() { Future<void> close() {
_subscription?.cancel(); // Supaya tidak bocor memorinya
return super.close(); return super.close();
} }
} }

View File

@ -0,0 +1,10 @@
import 'package:flutter/material.dart';
class WindSpeedScreen extends StatelessWidget {
const WindSpeedScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold();
}
}

View File

@ -1,205 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
url: "https://pub.dev"
source: hosted
version: "2.13.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
characters:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev"
source: hosted
version: "1.4.0"
clock:
dependency: transitive
description:
name: clock
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev"
source: hosted
version: "1.1.2"
collection:
dependency: transitive
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
version: "1.19.1"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev"
source: hosted
version: "1.3.3"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
url: "https://pub.dev"
source: hosted
version: "2.0.3"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev"
source: hosted
version: "11.0.2"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
lints:
dependency: transitive
description:
name: lints
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
matcher:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev"
source: hosted
version: "0.12.17"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.dev"
source: hosted
version: "1.17.0"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
source_span:
dependency: transitive
description:
name: source_span
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
url: "https://pub.dev"
source: hosted
version: "1.10.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.dev"
source: hosted
version: "1.12.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.dev"
source: hosted
version: "1.4.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.dev"
source: hosted
version: "1.2.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
url: "https://pub.dev"
source: hosted
version: "0.7.7"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
version: "2.2.0"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
url: "https://pub.dev"
source: hosted
version: "15.0.2"
sdks:
dart: ">=3.8.0-0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"

View File

@ -1,26 +0,0 @@
name: module_repository
description: The Repo that handles modules
publish_to: 'none'
version: 0.0.1
environment:
sdk: '>=3.1.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
# equatable: ^2.0.5
# firebase_auth: ^4.16.0
# cloud_firestore: ^4.9.2
# firebase_storage: ^11.6.0
# rxdart: ^0.27.7
# path: ^1.8.3
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true

View File

@ -17,11 +17,14 @@ class FirebaseMonitoringRepo implements MonitoringRepository {
) { ) {
/// === ambil data mentah dari firebase === /// /// === ambil data mentah dari firebase === ///
return _db.ref(path).onValue.map((event) { return _db.ref(path).onValue.map((event) {
/// == ambil value-nya dan pastikan tipenya map == /// final Object? value = event.snapshot.value;
final data = event.snapshot.value as Map<dynamic, dynamic>? ?? {};
/// == masukan ke dalam "pabrik" (mapper) agar jadi objek == /// if (value is Map) {
return mapper(data); return mapper(value);
} else {
// Jika data kosong atau bukan Map, berikan Map kosong agar mapper tidak crash
return mapper({});
}
}); });
} }

View File

@ -12,6 +12,7 @@ class FirebaseUserRepo implements UserRepository {
FirebaseAuth? firebaseAuth, FirebaseAuth? firebaseAuth,
}) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance; }) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
/// == Melakukan Implement User == ///
@override @override
Stream<MyUser?> get user { Stream<MyUser?> get user {
return _firebaseAuth.authStateChanges().flatMap((firebaseUser) async* { return _firebaseAuth.authStateChanges().flatMap((firebaseUser) async* {
@ -42,6 +43,7 @@ class FirebaseUserRepo implements UserRepository {
}); });
} }
/// == Melakukan Implement Sign in == ///
@override @override
Future<void> signIn(String email, String password) async { Future<void> signIn(String email, String password) async {
try { try {
@ -53,6 +55,7 @@ class FirebaseUserRepo implements UserRepository {
} }
} }
/// == Melakukan Implement Sign Up == ///
@override @override
Future<MyUser> signUp(MyUser myUser, String password) async { Future<MyUser> signUp(MyUser myUser, String password) async {
try { try {
@ -66,6 +69,7 @@ class FirebaseUserRepo implements UserRepository {
} }
} }
/// == Melakukan Implement Log Out == ///
@override @override
Future<void> logOut() async { Future<void> logOut() async {
await _firebaseAuth.signOut(); await _firebaseAuth.signOut();
@ -85,6 +89,7 @@ class FirebaseUserRepo implements UserRepository {
} }
} }
/// == Sign in with Google == ///
@override @override
Future<void> signInWithGoogle() async { Future<void> signInWithGoogle() async {
try { try {

View File

@ -33,6 +33,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.4" version: "8.1.4"
bloc_concurrency:
dependency: "direct main"
description:
name: bloc_concurrency
sha256: "456b7a3616a7c1ceb975c14441b3f198bf57d81cb95b7c6de5cb0c60201afcd8"
url: "https://pub.dev"
source: hosted
version: "0.2.5"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -596,6 +604,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.4"
stream_transform:
dependency: transitive
description:
name: stream_transform
sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
url: "https://pub.dev"
source: hosted
version: "2.1.1"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:

View File

@ -6,6 +6,7 @@ environment:
sdk: ^3.1.0 sdk: ^3.1.0
dependencies: dependencies:
bloc: ^8.1.0 bloc: ^8.1.0
bloc_concurrency: ^0.2.5
cloud_firestore: ^6.1.1 cloud_firestore: ^6.1.1
cupertino_icons: ^1.0.8 cupertino_icons: ^1.0.8
equatable: ^2.0.5 equatable: ^2.0.5
@ -19,11 +20,11 @@ dependencies:
google_fonts: ^8.0.2 google_fonts: ^8.0.2
google_sign_in: ^7.2.0 google_sign_in: ^7.2.0
intl: ^0.20.2 intl: ^0.20.2
monitoring_repository:
path: packages/monitoring_repository
rxdart: ^0.27.7 rxdart: ^0.27.7
user_repository: user_repository:
path: packages/user_repository path: packages/user_repository
monitoring_repository:
path: packages/monitoring_repository
dev_dependencies: dev_dependencies:
flutter_lints: ^3.0.0 flutter_lints: ^3.0.0

View File

@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html> <html>
<head> <head>
<!-- <!--
@ -14,23 +14,29 @@
This is a placeholder for base href that will be replaced by the value of This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`. the `--base-href` argument provided to `flutter build`.
--> -->
<base href="$FLUTTER_BASE_HREF"> <base href="$FLUTTER_BASE_HREF" />
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta content="IE=Edge" http-equiv="X-UA-Compatible" />
<meta name="description" content="A new Flutter project."> <meta name="description" content="A new Flutter project." />
<!-- iOS meta tags & icons --> <!-- iOS meta tags & icons -->
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="apple-mobile-web-app-title" content="klimatologiot"> <meta name="apple-mobile-web-app-title" content="klimatologiot" />
<link rel="apple-touch-icon" href="icons/Icon-192.png"> <link rel="apple-touch-icon" href="icons/Icon-192.png" />
<!-- Favicon --> <!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png" /> <link rel="icon" type="image/png" href="favicon.png" />
<title>klimatologiot</title> <title>klimatologiot</title>
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.json" />
<!-- Google -->
<meta
name="google-signin-client_id"
content="219079385989-8hkp1kg2pprs5k269s4c08r6rpdj1gjd.apps.googleusercontent.com"
/>
</head> </head>
<body> <body>
<script src="flutter_bootstrap.js" async></script> <script src="flutter_bootstrap.js" async></script>