diff --git a/.github/workflows/flutter-ci.yml b/.github/workflows/flutter-ci.yml
index 5f913d6f..5c94e182 100644
--- a/.github/workflows/flutter-ci.yml
+++ b/.github/workflows/flutter-ci.yml
@@ -20,13 +20,12 @@ jobs:
- uses: subosito/flutter-action@v2
with:
# Temporary fix to failing CI
- flutter-version: '3.16.4'
+ flutter-version: '3.22.2'
architecture: x64
# channel: "stable"
- run: flutter pub get
- run: dart format . --set-exit-if-changed
- run: flutter analyze .
- - run: flutter test
build:
strategy:
@@ -41,13 +40,12 @@ jobs:
- uses: subosito/flutter-action@v2
with:
# Temporary fix to failing CI
- flutter-version: '3.16.4'
+ flutter-version: '3.22.2'
architecture: x64
# channel: "stable"
- run: flutter pub get
- run: dart format . --set-exit-if-changed
- run: flutter analyze .
- - run: flutter test
# - run: flutter build apk
# - uses: actions/upload-artifact@v1
# with:
diff --git a/README.md b/README.md
index a0e6a47a..e31227e5 100755
--- a/README.md
+++ b/README.md
@@ -41,37 +41,56 @@ samples, guidance on mobile development, and a full API reference.
## Project Structure
-This project follows MVVM architecture with following structure:
+This project follows Clean architecture with following structure:
```bash
-beacon/lib/
-├── components/ # Shared Components such as dialog boxes, button, and other shared widgets
-├── enums/ # enum files
-| └── view_state.dart # defines view states i.e Idle, Busy, Error
-├── models/ # model classes: group, beacon, location, landmark, user
-├── queries/ # includes all graphql query strings
-├── services/ # services
-| ├── database_mutation_function.dart/ # Graphql Queries implementations
-| ├── navigation_service.dart/ # All required navigation services
-| └── ... # all config files
-├── utilities/ # Utilities that includes constants file
-├── views/ # Views/UI layer
-| ├── auth_screen.dart
-| ├── base_view.dart
-| ├── hike_screen.dart
-| ├── group_screen.dart
-| ├── home.dart
-├── viewmodels/ # Viewmodels layer
-├── splash_screen.dart # Very first screen displayed whilst data is loading
-├── router.dart # All routes to ease navigation
-├── locator.dart # dependency injection using get_it
-├── main.dart # <3 of the app
+beacon/
+├── lib/
+│ ├── config/ # Configuration files
+│ ├── core/ # Core application logic
+│ ├── data/
+│ │ ├── datasources/
+│ │ │ ├── local/ # Local data sources
+│ │ │ └── remote/ # Remote data sources
+│ │ ├── models/ # Data models
+│ │ └── repositories/ # Data repositories
+│ ├── domain/
+│ │ ├── entities/ # Domain entities
+│ │ ├── repositories/ # Domain repositories
+│ │ └── usecases/ # Domain use cases
+│ ├── presentation/
+│ │ ├── auth/
+│ │ │ ├── cubit/ # Authentication Cubit
+│ │ │ ├── widget/ # Authentication widgets
+│ │ │ └── screen/ # Authentication screens
+│ │ ├── home/
+│ │ │ ├── cubit/ # Home Cubit
+│ │ │ ├── widget/ # Home widgets
+│ │ │ └── screen/ # Home screens
+│ │ ├── group/
+│ │ │ ├── cubit/ # Group Cubit
+│ │ │ ├── widget/ # Group widgets
+│ │ │ └── screen/ # Group screens
+│ │ ├── hike/
+│ │ │ ├── cubit/ # Hike Cubit
+│ │ │ ├── widget/ # Hike widgets
+│ │ │ └── screen/ # Hike screens
+│ │ ├── widgets/ # Shared widgets used across all presentation folders
+│ │ └── splash_screen.dart # Initial screen displayed while loading
+├── main.dart # App entry point
+├── theme/ # Theme configurations
+├── locator.dart # Dependency injection setup (using get_it)
+├── router.dart # App navigation routes
```
## Screenshots
+
+
+
+
## Contributing
Whether you have some feauture requests/ideas, code improvements, refactoring, performance improvements, help is always Welcome. The more is done, better it gets.
@@ -84,4 +103,4 @@ If you found any bugs, consider opening an [issue](https://github.com/CCExtracto
We would love to hear from you! You may join gsoc-beacon channel of CCExtractor community through slack:
-[![Slack](https://img.shields.io/badge/chat-on_slack-purple.svg?style=for-the-badge&logo=slack)](https://ccextractor.org/public/general/support/)
+[![Slack](https://img.shields.io/badge/chat-on_slack-purple.svg?style=for-the-badge&logo=slack)](https://ccextractor.org/public/general/support/)
\ No newline at end of file
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 9572626d..e1d57237 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -26,7 +26,7 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply from: project(':flutter_config').projectDir.getPath() + "/dotenv.gradle"
android {
- compileSdkVersion 33
+ compileSdkVersion 34
buildToolsVersion '29.0.0'
sourceSets {
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 4bf22ad4..480c3165 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,42 +1,45 @@
+
+
-
+
+
+
-
+ android:usesCleartextTraffic="true"
+ android:requestLegacyExternalStorage="true">
+
+
+
-
-
+
+
+
@@ -45,8 +48,7 @@
-
+
diff --git a/android/app/src/main/kotlin/com/example/beacon/MainActivity.kt b/android/app/src/main/kotlin/com/example/beacon/MainActivity.kt
index 7e21f388..0553af8d 100644
--- a/android/app/src/main/kotlin/com/example/beacon/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/example/beacon/MainActivity.kt
@@ -1,6 +1,21 @@
package com.example.beacon
+import android.content.res.Configuration
+import androidx.annotation.NonNull
+import cl.puntito.simple_pip_mode.PipCallbackHelper
import io.flutter.embedding.android.FlutterActivity
+import io.flutter.embedding.engine.FlutterEngine
-class MainActivity: FlutterActivity() {
+class MainActivity : FlutterActivity() {
+ private var callbackHelper = PipCallbackHelper()
+
+ override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
+ super.configureFlutterEngine(flutterEngine)
+ callbackHelper.configureFlutterEngine(flutterEngine)
+ }
+
+ override fun onPictureInPictureModeChanged(active: Boolean, newConfig: Configuration?) {
+ super.onPictureInPictureModeChanged(active, newConfig)
+ callbackHelper.onPictureInPictureModeChanged(active)
+ }
}
diff --git a/images/filter_icon.png b/images/filter_icon.png
new file mode 100644
index 00000000..c0d1b31f
Binary files /dev/null and b/images/filter_icon.png differ
diff --git a/images/google.png b/images/google.png
new file mode 100644
index 00000000..0ea3fd5b
Binary files /dev/null and b/images/google.png differ
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 9625e105..7c569640 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 11.0
+ 12.0
diff --git a/ios/Podfile b/ios/Podfile
index 88359b22..279576f3 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '11.0'
+# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index f59742c4..d5fe87e7 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -88,22 +88,22 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
- Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
+ Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_config: f48f0d47a284f1791aacce2687eabb3309ba7a41
- flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
+ flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265
geolocator_apple: 9157311f654584b9bb72686c55fc02a97b73f461
- google_maps_flutter_ios: 590249c67f34f422122c232f2a626192adbc78ee
+ google_maps_flutter_ios: d1318b4ff711612cab16862d7a87e31a7403d458
GoogleMaps: 025272d5876d3b32604e5c080dc25eaf68764693
- location: 3a2eed4dd2fab25e7b7baf2a9efefe82b512d740
+ location: d5cf8598915965547c3f36761ae9cc4f4e87d22e
modal_progress_hud_nsn: f6fb744cd060653d66ed8f325360ef3650eb2fde
- path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
+ path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
- shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
+ shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
-PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
+PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011
-COCOAPODS: 1.14.2
+COCOAPODS: 1.15.2
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 5edd6cee..b4a0eff2 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -157,7 +157,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1430;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -361,7 +361,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -438,7 +438,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -487,7 +487,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index b52b2e69..e67b2808 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
token);
-
- static WebSocketLink websocketLink =
- WebSocketLink(EnvironmentConfig.websocketEndpoint!,
- config: SocketClientConfig(
- autoReconnect: true,
- initialPayload: {
- "Authorization": '${userConfig!.currentUser!.authToken}'
- },
- ));
-
- Future getToken() async {
- await localApi.init();
- final user = await localApi.fetchUser();
- if (user != null) {
- token = user.authToken;
- }
- return true;
- }
-
- GraphQLClient clientToQuery() {
- return GraphQLClient(
- cache: GraphQLCache(partialDataPolicy: PartialDataCachePolicy.accept),
- link: httpLink,
- );
- }
-
- Future authClient() async {
- await getToken();
- final AuthLink authLink = AuthLink(getToken: () async => '$token');
- final Link finalAuthLink = authLink.concat(httpLink);
- return GraphQLClient(
- cache: GraphQLCache(partialDataPolicy: PartialDataCachePolicy.accept),
- link: finalAuthLink,
- );
- }
-
- GraphQLClient graphQlClient() {
- return GraphQLClient(
- cache: GraphQLCache(partialDataPolicy: PartialDataCachePolicy.accept),
- link: Link.split(
- (request) => request.isSubscription,
- websocketLink,
- authLink.concat(httpLink),
- ),
- );
- }
-}
diff --git a/lib/Bloc/config/user_config.dart b/lib/Bloc/config/user_config.dart
deleted file mode 100644
index c0e88e30..00000000
--- a/lib/Bloc/config/user_config.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-import 'package:beacon/Bloc/data/models/user/user_model.dart';
-import 'package:beacon/locator.dart';
-
-class UserModelConfig {
- UserModel _userModel = UserModel(authToken: 'null');
- UserModel get userModel => _userModel;
-
- Future updateUser(UserModel updateUserDetails) async {
- _userModel = updateUserDetails;
- return localApi.saveUser(updateUserDetails);
- }
-}
diff --git a/lib/Bloc/core/constants/location.dart b/lib/Bloc/core/constants/location.dart
deleted file mode 100644
index 0e72c7cc..00000000
--- a/lib/Bloc/core/constants/location.dart
+++ /dev/null
@@ -1,30 +0,0 @@
-import 'package:geolocator/geolocator.dart';
-
-class LocationService {
- static Future getCurrentLocation() async {
- bool serviceEnabled;
- LocationPermission permission;
-
- serviceEnabled = await Geolocator.isLocationServiceEnabled();
-
- if (!serviceEnabled) {
- return Future.error('Location service is disabled.');
- }
-
- permission = await Geolocator.checkPermission();
-
- if (permission == LocationPermission.denied) {
- permission = await Geolocator.requestPermission();
- if (permission == LocationPermission.denied) {
- return Future.error('Location permission is denied');
- }
- }
-
- if (permission == LocationPermission.deniedForever) {
- return Future.error('Location permission is permanently denied.');
- }
-
- return await Geolocator.getCurrentPosition(
- desiredAccuracy: LocationAccuracy.high);
- }
-}
diff --git a/lib/Bloc/core/services/size_config.dart b/lib/Bloc/core/services/size_config.dart
deleted file mode 100644
index 0dd0d64d..00000000
--- a/lib/Bloc/core/services/size_config.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-import 'package:flutter/material.dart';
-
-class SizeConfig {
- static late MediaQueryData _mediaQueryData;
- static late double screenWidth;
- static late double screenHeight;
- static double? blockSizeHorizontal;
- static double? blockSizeVertical;
- static double? paddingTop;
-
- static late double _safeAreaHorizontal;
- static late double _safeAreaVertical;
- static double? safeBlockHorizontal;
- static double? safeBlockVertical;
-
- void init(BuildContext context) {
- _mediaQueryData = MediaQuery.of(context);
- screenWidth = _mediaQueryData.size.width;
- screenHeight = _mediaQueryData.size.height;
- blockSizeHorizontal = screenWidth / 100;
- blockSizeVertical = screenHeight / 100;
-
- _safeAreaHorizontal =
- _mediaQueryData.padding.left + _mediaQueryData.padding.right;
- _safeAreaVertical =
- _mediaQueryData.padding.top + _mediaQueryData.padding.bottom;
- safeBlockHorizontal = (screenWidth - _safeAreaHorizontal) / 100;
- safeBlockVertical = (screenHeight - _safeAreaVertical) / 100;
- debugPrint("safeBlockHorizontal: $safeBlockHorizontal");
- debugPrint("safeBlockVertical: $safeBlockVertical");
- }
-}
diff --git a/lib/Bloc/core/usercase/usecase.dart b/lib/Bloc/core/usercase/usecase.dart
deleted file mode 100644
index 2d8b44d1..00000000
--- a/lib/Bloc/core/usercase/usecase.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-abstract class UseCase {
- Future call(Paramas paramas);
-}
diff --git a/lib/Bloc/core/utils/validators.dart b/lib/Bloc/core/utils/validators.dart
deleted file mode 100644
index febbefc9..00000000
--- a/lib/Bloc/core/utils/validators.dart
+++ /dev/null
@@ -1,77 +0,0 @@
-class Validator {
- static String? validateName(String? name) {
- if (name != null && name.isEmpty) {
- return "Name must not be left blank";
- }
- return null;
- }
-
- static String? validateEmail(String? email) {
- // If email is empty return.
- if (email != null && email.isEmpty) {
- return "Email must not be left blank";
- }
- const String pattern =
- r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$";
- final RegExp regex = RegExp(pattern);
- if (email != null && !regex.hasMatch(email)) {
- return 'Please enter a valid Email Address';
- }
- return null;
- }
-
- static String? validatePassword(String? password) {
- // If password is empty return.
- if (password != null && password.isEmpty) {
- return "Password must not be left blank";
- }
- // const String pattern = r'^(?=.*?[0-9])(?=.*?[!@#\$&*%^~.]).{8,}$';
- // final RegExp regExp = RegExp(pattern);
-
- //Regex for no spaces allowed
- const String noSpaces = r'^\S+$';
- final RegExp noSpaceRegex = RegExp(noSpaces);
-
- if (password!.length < 8) {
- return "Must be of atleast 8 characters";
- }
- // if (!regExp.hasMatch(password)) {
- // return "At least 1 number and symbol required";
- // }
- if (!noSpaceRegex.hasMatch(password)) {
- return "Password must not contain spaces";
- }
- return null;
- }
-
- static String? validateBeaconTitle(String? title) {
- if (title != null && title.isEmpty) {
- return "Title must not be left blank";
- }
- return null;
- }
-
- static String? validatePasskey(String? passkey) {
- if (passkey != null && passkey.isEmpty) {
- return "Passkey must not be left blank";
- }
- const String pattern = r'[A-Z]+';
- final RegExp regExp = RegExp(pattern);
- if (!regExp.hasMatch(passkey!) || passkey.length != 6) {
- return "Invalid passkey";
- }
- return null;
- }
-
- static String? validateDuration(String? duration) {
- if (duration != null && duration.startsWith("0:00:00.")) {
- return "Duration cannot be $duration";
- }
- return null;
- }
-
- static String? validateStartingTime(String? startTime) {
- print(startTime);
- return null;
- }
-}
diff --git a/lib/Bloc/data/datasource/remote/remote_auth_api.dart b/lib/Bloc/data/datasource/remote/remote_auth_api.dart
deleted file mode 100644
index d40bcb3a..00000000
--- a/lib/Bloc/data/datasource/remote/remote_auth_api.dart
+++ /dev/null
@@ -1,137 +0,0 @@
-import 'package:beacon/Bloc/core/queries/auth.dart';
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/data/models/user/user_model.dart';
-import 'package:beacon/locator.dart';
-import 'package:flutter/material.dart';
-import 'package:graphql_flutter/graphql_flutter.dart';
-
-class RemoteAuthApi {
- final ValueNotifier clientNonAuth;
- GraphQLClient clientAuth;
-
- RemoteAuthApi({
- required this.clientNonAuth,
- required this.clientAuth,
- });
-
- AuthQueries _authQueries = AuthQueries();
-
- Future> fetchUserInfo() async {
- clientAuth = await graphqlConfig.authClient();
-
- final isConnected = await utils.checkInternetConnectivity();
-
- if (!isConnected)
- return DataFailed('Beacon is trying to connect with internet...');
-
- // api call
- final result = await clientAuth
- .mutate(MutationOptions(document: gql(_authQueries.fetchUserInfo())));
-
- if (result.data != null && result.isConcrete) {
- final json = result.data!['me'];
- final user = UserModel.fromJson(json);
-
- final currentUser = await localApi.fetchUser();
-
- // checking if user is login
- if (currentUser == null) return DataFailed('Please login first');
- final newUser = user.copyWithModel(
- authToken: currentUser.authToken,
- isGuest: user.email == '' ? true : false);
-
- // saving user details locally
- await localApi.saveUser(newUser);
-
- // returning
- return DataSuccess(newUser);
- }
- return DataFailed(encounteredExceptionOrError(result.exception!));
- }
-
- Future> register(
- String name, String email, String password) async {
- try {
- final isConnected = await utils.checkInternetConnectivity();
-
- if (!isConnected)
- return DataFailed('Beacon is trying to connect with internet...');
-
- final result = await clientNonAuth.value.mutate(
- MutationOptions(
- document: gql(_authQueries.registerUser(name, email, password)),
- ),
- );
-
- if (result.data != null && result.isConcrete) {
- // LOGIN API CALL
- final dataState = await login(email, password);
- return dataState;
- } else if (result.hasException) {
- final message = encounteredExceptionOrError(result.exception!);
- return DataFailed(message);
- }
-
- return DataFailed('An unexpected error occurred during registration.');
- } catch (e) {
- return DataFailed(e.toString());
- }
- }
-
- Future> login(String email, String password) async {
- try {
- final isConnected = await utils.checkInternetConnectivity();
-
- if (!isConnected) {
- return DataFailed('Beacon is trying to connect with internet...');
- }
-
- final QueryResult result = await clientNonAuth.value.mutate(
- MutationOptions(
- document: gql(_authQueries.loginUser(email, password))));
-
- if (result.data != null && result.isConcrete) {
- final token = "Bearer ${result.data!['login']}";
-
- // storing auth token in hive
- final user =
- UserModel(authToken: token, isGuest: (email == '') ? true : false);
- await localApi.saveUser(user);
-
- // fetching User Info
-
- final dataState = await fetchUserInfo();
-
- if (dataState is DataSuccess) {
- final updatedUser = dataState.data!
- .copyWithModel(authToken: user.authToken, isGuest: user.isGuest);
-
- // if(locator.isRegistered( ))
-
- // saving locally
- await localApi.saveUser(updatedUser);
-
- return dataState;
- }
- return dataState;
- } else if (result.hasException) {
- final message = encounteredExceptionOrError(result.exception!);
-
- return DataFailed(message);
- }
-
- return DataFailed('An unexpected error occured.');
- } catch (e) {
- return DataFailed(e.toString());
- }
- }
-
- String encounteredExceptionOrError(OperationException exception) {
- if (exception.linkException != null) {
- debugPrint(exception.linkException.toString());
- return 'Server not running';
- } else {
- return exception.graphqlErrors[0].message.toString();
- }
- }
-}
diff --git a/lib/Bloc/data/datasource/remote/remote_group_api.dart b/lib/Bloc/data/datasource/remote/remote_group_api.dart
deleted file mode 100644
index 7203aae7..00000000
--- a/lib/Bloc/data/datasource/remote/remote_group_api.dart
+++ /dev/null
@@ -1,130 +0,0 @@
-import 'dart:developer';
-
-import 'package:beacon/Bloc/core/queries/beacon.dart';
-import 'package:beacon/Bloc/core/queries/group.dart';
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/data/models/beacon/beacon_model.dart';
-import 'package:beacon/Bloc/data/models/group/group_model.dart';
-import 'package:beacon/locator.dart';
-import 'package:graphql_flutter/graphql_flutter.dart';
-
-class RemoteGroupApi {
- final GraphQLClient authClient;
-
- RemoteGroupApi({required this.authClient});
-
- final _groupqueries = GroupQueries();
-
- final _beaconQueries = BeaconQueries();
-
- Future>> fetchHikes(
- String groupId, int page, int pageSize) async {
- bool isConnected = await utils.checkInternetConnectivity();
-
- if (!isConnected) {
- GroupModel? group = await localApi.getGroup(groupId);
-
- if (group != null && group.beacons != null) {
- int condition = (page - 1) * pageSize + pageSize;
- int beaconLen = group.beacons!.length;
-
- if (condition > beaconLen) {
- condition = beaconLen;
- }
-
- List beacons = [];
-
- for (int i = (page - 1) * pageSize; i < condition; i++) {
- BeaconModel? beaconModel =
- await localApi.getBeacon(group.beacons![i]!.id);
-
- beaconModel != null ? beacons.add(beaconModel) : null;
- }
-
- return DataSuccess(beacons);
- }
-
- return DataFailed('Please check your internet connection!');
- }
-
- final authClient = await graphqlConfig.authClient();
- final result = await authClient.query(QueryOptions(
- document: gql(_groupqueries.fetchHikes(groupId, page, pageSize))));
-
- if (result.data != null && result.isConcrete) {
- List hikesJson = result.data!['beacons'];
-
- List hikes = [];
-
- for (var hikeJson in hikesJson) {
- BeaconModel hike = BeaconModel.fromJson(hikeJson);
- hikes.add(hike);
-
- // storing beacon
- if (1 == 1) {
- log('called');
- await localApi.saveBeacon(hike);
- }
- }
-
- return DataSuccess(hikes);
- }
- return DataFailed(encounteredExceptionOrError(result.exception!));
- }
-
- Future> createHike(String title, int startsAt,
- int expiresAt, String lat, String lon, String groupID) async {
- final authClient = await graphqlConfig.authClient();
-
- bool isConnected = await utils.checkInternetConnectivity();
-
- if (!isConnected) {
- return DataFailed('Please check your internet connection!');
- }
- final result = await authClient.mutate(MutationOptions(
- document: gql(_beaconQueries.createBeacon(
- title, startsAt, expiresAt, lat, lon, groupID))));
-
- if (result.data != null && result.isConcrete) {
- final hikeJson = result.data!['createBeacon'];
-
- final beacon = BeaconModel.fromJson(hikeJson);
-
- // storing beacon
- await localApi.saveBeacon(beacon);
- return DataSuccess(beacon);
- }
- return DataFailed(encounteredExceptionOrError(result.exception!));
- }
-
- Future> joinHike(String shortcode) async {
- bool isConnected = await utils.checkInternetConnectivity();
-
- if (!isConnected) {
- return DataFailed('Please check your internet connection!');
- }
- final authClient = await graphqlConfig.authClient();
- final result = await authClient.mutate(
- MutationOptions(document: gql(_beaconQueries.joinBeacon(shortcode))));
-
- if (result.data != null && result.isConcrete) {
- final hikeJosn = result.data!['joinBeacon'];
-
- final beacon = BeaconModel.fromJson(hikeJosn);
-
- // storing beacon
- await localApi.saveBeacon(beacon);
-
- return DataSuccess(beacon);
- }
- return DataFailed(encounteredExceptionOrError(result.exception!));
- }
-
- String encounteredExceptionOrError(OperationException exception) {
- if (exception.linkException != null) {
- return 'Server not running';
- } else {
- return exception.graphqlErrors[0].message.toString();
- }
- }
-}
diff --git a/lib/Bloc/data/datasource/remote/remote_home_api.dart b/lib/Bloc/data/datasource/remote/remote_home_api.dart
deleted file mode 100644
index 06fba351..00000000
--- a/lib/Bloc/data/datasource/remote/remote_home_api.dart
+++ /dev/null
@@ -1,123 +0,0 @@
-import 'package:beacon/Bloc/core/queries/group.dart';
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/data/models/group/group_model.dart';
-import 'package:beacon/Bloc/data/models/user/user_model.dart';
-import 'package:beacon/locator.dart';
-import 'package:flutter/material.dart';
-import 'package:graphql_flutter/graphql_flutter.dart';
-
-class RemoteHomeApi {
- final GraphQLClient _clientAuth;
- RemoteHomeApi(this._clientAuth);
-
- final _groupQueries = GroupQueries();
-
- Future>> fetchUserGroups(
- int page, int pageSize) async {
- final isConnected = await utils.checkInternetConnectivity();
-
- print(_clientAuth.toString());
-
- if (!isConnected) {
- // fetching the previous data stored
- // here taking all the ids of group from the user model and then fetching the groups locally from the ids
- // returning all groups in one go
- UserModel? usermodel = await localApi.fetchUser();
-
- if (usermodel != null && usermodel.groups != null) {
- // taking user groups
-
- int condition = (page - 1) * pageSize + pageSize;
- int groupLen = usermodel.groups!.length;
-
- if (condition > groupLen) {
- condition = groupLen;
- }
-
- List groups = [];
-
- for (int i = (page - 1) * pageSize; i < condition; i++) {
- GroupModel? groupModel =
- await localApi.getGroup(usermodel.groups![i]!.id);
- groupModel != null ? groups.add(groupModel) : null;
- }
-
- return DataSuccess(groups);
- }
- }
-
- final clientAuth = await graphqlConfig.authClient();
-
- final result = await clientAuth.query(QueryOptions(
- document: gql(_groupQueries.fetchUserGroups(page, pageSize))));
-
- if (result.data != null && result.isConcrete) {
- List groups = [];
- List groupsData = result.data!['groups'];
- for (var groupData in groupsData) {
- final group = GroupModel.fromJson(groupData);
-
- // saving locally
- await localApi.saveGroup(group);
-
- groups.add(group);
- }
- return DataSuccess(groups);
- }
-
- return DataFailed(encounteredExceptionOrError(result.exception!));
- }
-
- Future> createGroup(String title) async {
- final isConnected = await utils.checkInternetConnectivity();
-
- if (!isConnected)
- return DataFailed('Beacon is trying to connect with internet...');
- final _clientAuth = await graphqlConfig.authClient();
- final result = await _clientAuth.mutate(
- MutationOptions(document: gql(_groupQueries.createGroup(title))));
-
- if (result.data != null && result.isConcrete) {
- GroupModel group = GroupModel.fromJson(
- result.data!['createGroup'] as Map);
-
- // storing group
- await localApi.saveGroup(group);
-
- return DataSuccess(group);
- }
-
- return DataFailed(encounteredExceptionOrError(result.exception!));
- }
-
- Future> joinGroup(String shortCode) async {
- final isConnected = await utils.checkInternetConnectivity();
-
- if (!isConnected)
- return DataFailed('Beacon is trying to connect with internet...');
- final _clientAuth = await graphqlConfig.authClient();
- final result = await _clientAuth.mutate(
- MutationOptions(document: gql(_groupQueries.joinGroup(shortCode))));
-
- if (result.data != null && result.isConcrete) {
- GroupModel group =
- GroupModel.fromJson(result.data as Map);
-
- // storing group
- await localApi.saveGroup(group);
-
- return DataSuccess(group);
- }
-
- return DataFailed(encounteredExceptionOrError(result.exception!));
- }
-
- String encounteredExceptionOrError(OperationException exception) {
- if (exception.linkException != null) {
- debugPrint(exception.linkException.toString());
- return 'Server not running';
- } else {
- return exception.graphqlErrors[0].message.toString();
- }
- }
-}
diff --git a/lib/Bloc/data/models/landmark/landmark_model.dart b/lib/Bloc/data/models/landmark/landmark_model.dart
deleted file mode 100644
index 779c3c29..00000000
--- a/lib/Bloc/data/models/landmark/landmark_model.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-import 'package:beacon/Bloc/data/models/location/location_model.dart';
-import 'package:beacon/Bloc/domain/entities/landmark/landmark_entity.dart';
-import 'package:hive/hive.dart';
-import 'package:json_annotation/json_annotation.dart';
-
-part 'landmark_model.g.dart';
-
-@HiveType(typeId: 50)
-@JsonSerializable()
-class LandMarkModel implements LandMarkEntity {
- @HiveField(0)
- String? title;
- @HiveField(1)
- LocationModel? location;
-
- LandMarkModel({this.title, this.location});
-
- @override
- $LandMarkEntityCopyWith get copyWith =>
- throw UnimplementedError();
-
- factory LandMarkModel.fromJson(Map json) =>
- _$LandMarkModelFromJson(json);
-
- Map toJson() => _$LandMarkModelToJson(this);
-
- LandMarkModel copyWithModel({
- String? title,
- LocationModel? location,
- }) {
- return LandMarkModel(
- title: title ?? this.title,
- location: location ?? this.location,
- );
- }
-}
diff --git a/lib/Bloc/data/repositories/auth_repository_implementation.dart b/lib/Bloc/data/repositories/auth_repository_implementation.dart
deleted file mode 100644
index 3ed41e6e..00000000
--- a/lib/Bloc/data/repositories/auth_repository_implementation.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/data/datasource/remote/remote_auth_api.dart';
-import 'package:beacon/Bloc/data/models/user/user_model.dart';
-import 'package:beacon/Bloc/domain/repositories/auth_repository.dart';
-
-class AuthRepositoryImplementation extends AuthRepository {
- final RemoteAuthApi remoteAuthApi;
-
- AuthRepositoryImplementation({required this.remoteAuthApi});
-
- @override
- Future> getUser() {
- return remoteAuthApi.fetchUserInfo();
- }
-
- @override
- Future> login(String email, String password) {
- return remoteAuthApi.login(email, password);
- }
-
- @override
- Future> register(
- String name, String email, String password) {
- return remoteAuthApi.register(name, email, password);
- }
-}
diff --git a/lib/Bloc/data/repositories/group_repository_implementation.dart b/lib/Bloc/data/repositories/group_repository_implementation.dart
deleted file mode 100644
index 94ada788..00000000
--- a/lib/Bloc/data/repositories/group_repository_implementation.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/data/datasource/remote/remote_group_api.dart';
-import 'package:beacon/Bloc/data/models/beacon/beacon_model.dart';
-import 'package:beacon/Bloc/domain/repositories/group_repository.dart';
-
-class GroupRepostioryImplementation extends GroupRepository {
- final RemoteGroupApi remoteGroupApi;
- GroupRepostioryImplementation({required this.remoteGroupApi});
- @override
- Future> createHike(String title, int startsAt,
- int expiresAt, String lat, String lon, String groupID) async {
- return remoteGroupApi.createHike(
- title, startsAt, expiresAt, lat, lon, groupID);
- }
-
- @override
- Future>> fetchHikes(
- String groupID, int page, int pageSize) {
- return remoteGroupApi.fetchHikes(groupID, page, pageSize);
- }
-
- @override
- Future> joinHike(String shortcode) {
- return remoteGroupApi.joinHike(shortcode);
- }
-}
diff --git a/lib/Bloc/data/repositories/home_repository_implementation.dart b/lib/Bloc/data/repositories/home_repository_implementation.dart
deleted file mode 100644
index c63b036b..00000000
--- a/lib/Bloc/data/repositories/home_repository_implementation.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/data/datasource/remote/remote_home_api.dart';
-import 'package:beacon/Bloc/data/models/group/group_model.dart';
-import 'package:beacon/Bloc/domain/repositories/home_repository.dart';
-
-class HomeRepostitoryImplementation extends HomeRepository {
- final RemoteHomeApi remoteHomeApi;
-
- HomeRepostitoryImplementation({required this.remoteHomeApi});
-
- @override
- Future> createGroup(String title) {
- return remoteHomeApi.createGroup(title);
- }
-
- @override
- Future>> fetchGroups(int page, int pageSize) {
- return remoteHomeApi.fetchUserGroups(page, pageSize);
- }
-
- @override
- Future> joinGroup(String shortCode) {
- return remoteHomeApi.joinGroup(shortCode);
- }
-}
diff --git a/lib/Bloc/domain/entities/beacon/beacon_entity.dart b/lib/Bloc/domain/entities/beacon/beacon_entity.dart
deleted file mode 100644
index 2f1ce48c..00000000
--- a/lib/Bloc/domain/entities/beacon/beacon_entity.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-import 'package:beacon/Bloc/domain/entities/group/group_entity.dart';
-import 'package:beacon/Bloc/domain/entities/landmark/landmark_entity.dart';
-import 'package:beacon/Bloc/domain/entities/location/location_entity.dart';
-import 'package:beacon/Bloc/domain/entities/user/user_entity.dart';
-import 'package:freezed_annotation/freezed_annotation.dart';
-
-part 'beacon_entity.freezed.dart';
-
-@freezed
-class BeaconEntity with _$BeaconEntity {
- const factory BeaconEntity(
- {String? id,
- String? shortcode,
- int? startsAt,
- int? expiresAt,
- String? title,
- UserEntity? leader,
- List? followers,
- List? route,
- List? landmarks,
- LocationEntity? location,
- GroupEntity? group}) = _BeaconEntity;
-}
diff --git a/lib/Bloc/domain/entities/group/group_entity.dart b/lib/Bloc/domain/entities/group/group_entity.dart
deleted file mode 100644
index d036619f..00000000
--- a/lib/Bloc/domain/entities/group/group_entity.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-import 'package:beacon/Bloc/domain/entities/beacon/beacon_entity.dart';
-import 'package:beacon/Bloc/domain/entities/user/user_entity.dart';
-import 'package:freezed_annotation/freezed_annotation.dart';
-
-part 'group_entity.freezed.dart';
-
-@freezed
-class GroupEntity with _$GroupEntity {
- const factory GroupEntity({
- String? id,
- List? beacons,
- List? members,
- UserEntity? leader,
- String? title,
- String? shortcode,
- }) = _GroupEntity;
-}
diff --git a/lib/Bloc/domain/entities/landmark/landmark_entity.dart b/lib/Bloc/domain/entities/landmark/landmark_entity.dart
deleted file mode 100644
index 883699ec..00000000
--- a/lib/Bloc/domain/entities/landmark/landmark_entity.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-import 'package:beacon/Bloc/domain/entities/location/location_entity.dart';
-import 'package:freezed_annotation/freezed_annotation.dart';
-part 'landmark_entity.freezed.dart';
-
-@freezed
-class LandMarkEntity with _$LandMarkEntity {
- const factory LandMarkEntity({String? title, LocationEntity? location}) =
- _LandMarkEntity;
-}
diff --git a/lib/Bloc/domain/entities/location/location_entity.dart b/lib/Bloc/domain/entities/location/location_entity.dart
deleted file mode 100644
index 6f7448a9..00000000
--- a/lib/Bloc/domain/entities/location/location_entity.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-import 'package:freezed_annotation/freezed_annotation.dart';
-part 'location_entity.freezed.dart';
-
-@freezed
-class LocationEntity with _$LocationEntity {
- factory LocationEntity({String? lat, String? lon}) = _LocationEntity;
-}
diff --git a/lib/Bloc/domain/entities/user/user_entity.dart b/lib/Bloc/domain/entities/user/user_entity.dart
deleted file mode 100644
index d82447f4..00000000
--- a/lib/Bloc/domain/entities/user/user_entity.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-import 'package:beacon/Bloc/domain/entities/beacon/beacon_entity.dart';
-import 'package:beacon/Bloc/domain/entities/group/group_entity.dart';
-import 'package:beacon/Bloc/domain/entities/location/location_entity.dart';
-import 'package:freezed_annotation/freezed_annotation.dart';
-
-part 'user_entity.freezed.dart';
-
-@freezed
-class UserEntity with _$UserEntity {
- const factory UserEntity(
- {String? id,
- List? groups,
- List? beacons,
- String? authToken,
- String? email,
- bool? isGuest,
- String? name,
- LocationEntity? location}) = _UserEntity;
-}
diff --git a/lib/Bloc/domain/repositories/group_repository.dart b/lib/Bloc/domain/repositories/group_repository.dart
deleted file mode 100644
index 36bb561a..00000000
--- a/lib/Bloc/domain/repositories/group_repository.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/domain/entities/beacon/beacon_entity.dart';
-
-abstract class GroupRepository {
- Future> createHike(String title, int startsAt,
- int expiresAt, String lat, String lon, String groupID);
-
- Future> joinHike(String hikeId);
-
- Future>> fetchHikes(
- String groupID, int page, int pageSize);
-}
diff --git a/lib/Bloc/domain/repositories/home_repository.dart b/lib/Bloc/domain/repositories/home_repository.dart
deleted file mode 100644
index 23a7dff5..00000000
--- a/lib/Bloc/domain/repositories/home_repository.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/domain/entities/group/group_entity.dart';
-
-abstract class HomeRepository {
- Future>> fetchGroups(int page, int pageSize);
- Future> createGroup(String title);
- Future> joinGroup(String shortCode);
-}
diff --git a/lib/Bloc/domain/usecase/auth_usecase.dart b/lib/Bloc/domain/usecase/auth_usecase.dart
deleted file mode 100644
index 3ce63073..00000000
--- a/lib/Bloc/domain/usecase/auth_usecase.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/domain/entities/user/user_entity.dart';
-import 'package:beacon/Bloc/domain/repositories/auth_repository.dart';
-
-class AuthUseCase {
- final AuthRepository authRepository;
-
- AuthUseCase({required this.authRepository});
-
- Future> registerUseCase(
- String name, String email, String password) async {
- return await authRepository.register(name, email, password);
- }
-
- Future> loginUserCase(
- String email, String password) async {
- return await authRepository.login(email, password);
- }
-
- Future> getUserInfoUseCase() async {
- return await authRepository.getUser();
- }
-}
diff --git a/lib/Bloc/domain/usecase/group_usecase.dart b/lib/Bloc/domain/usecase/group_usecase.dart
deleted file mode 100644
index 6122caee..00000000
--- a/lib/Bloc/domain/usecase/group_usecase.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/domain/entities/beacon/beacon_entity.dart';
-import 'package:beacon/Bloc/domain/repositories/group_repository.dart';
-
-class GroupUseCase {
- final GroupRepository _groupRepo;
-
- GroupUseCase(this._groupRepo);
-
- Future>> fetchHikes(
- String groupID, int page, int pageSize) {
- return _groupRepo.fetchHikes(groupID, page, pageSize);
- }
-
- Future> joinHike(String shortcode) {
- return _groupRepo.joinHike(shortcode);
- }
-
- Future> createHike(String title, int startsAt,
- int expiresAt, String lat, String lon, String groupID) {
- return _groupRepo.createHike(title, startsAt, expiresAt, lat, lon, groupID);
- }
-}
diff --git a/lib/Bloc/domain/usecase/home_usecase.dart b/lib/Bloc/domain/usecase/home_usecase.dart
deleted file mode 100644
index 995f7818..00000000
--- a/lib/Bloc/domain/usecase/home_usecase.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/domain/entities/group/group_entity.dart';
-import 'package:beacon/Bloc/domain/repositories/home_repository.dart';
-
-class HomeUseCase {
- final HomeRepository homeRepository;
-
- HomeUseCase({required this.homeRepository});
-
- Future>> groups(int page, int pageSize) {
- return homeRepository.fetchGroups(page, pageSize);
- }
-
- Future> createGroup(String title) {
- return homeRepository.createGroup(title);
- }
-
- Future> joinGroup(String shortCode) {
- return homeRepository.joinGroup(shortCode);
- }
-}
diff --git a/lib/Bloc/presentation/cubit/auth_cubit.dart b/lib/Bloc/presentation/cubit/auth_cubit.dart
deleted file mode 100644
index 0daf56fb..00000000
--- a/lib/Bloc/presentation/cubit/auth_cubit.dart
+++ /dev/null
@@ -1,84 +0,0 @@
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/domain/entities/user/user_entity.dart';
-import 'package:beacon/Bloc/domain/usecase/auth_usecase.dart';
-import 'package:beacon/locator.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-abstract class AuthState {
- final UserEntity? user;
- final String? message;
- final String? error;
-
- AuthState({this.error, this.message, this.user});
-}
-
-class IconToggled extends AuthState {
- final bool isIconChecked;
-
- IconToggled(this.isIconChecked);
-}
-
-class InitialAuthState extends AuthState {}
-
-class AuthLoadingState extends AuthState {}
-
-class AuthErrorState extends AuthState {
- final String? error;
- AuthErrorState({required this.error});
-}
-
-class SuccessState extends AuthState {
- final String? message;
- final UserEntity? user;
- SuccessState({this.message, this.user});
-}
-
-class AuthCubit extends Cubit {
- final AuthUseCase authUseCase;
- AuthCubit({required this.authUseCase}) : super(InitialAuthState());
-
- Future register(
- String name,
- String email,
- String password,
- ) async {
- emit(AuthLoadingState());
- final state = await authUseCase.registerUseCase(name, email, password);
- if (state is DataFailed) {
- emit(AuthErrorState(error: state.error));
- } else {
- emit(SuccessState(user: state.data));
- }
- }
-
- Future login(String email, String password) async {
- emit(AuthLoadingState());
- final state = await authUseCase.loginUserCase(email, password);
- if (state is DataFailed) {
- emit(AuthErrorState(error: state.error));
- } else {
- emit(SuccessState(user: state.data));
- }
- }
-
- Future fetchUserInfo() async {
- final userInfo = await authUseCase.getUserInfoUseCase();
-
- if (userInfo is DataFailed) {
- emit(AuthErrorState(error: userInfo.error!));
- } else {
- emit(SuccessState(user: userInfo.data));
- }
- }
-
- requestFocus(FocusNode focusNode, BuildContext context) {
- FocusScope.of(context).requestFocus(focusNode);
- }
-
- Future isGuest() async {
- bool? isguest = await localApi.userModel.isGuest;
-
- return isguest!;
- }
-}
diff --git a/lib/Bloc/presentation/cubit/group_cubit.dart b/lib/Bloc/presentation/cubit/group_cubit.dart
deleted file mode 100644
index 34c8a941..00000000
--- a/lib/Bloc/presentation/cubit/group_cubit.dart
+++ /dev/null
@@ -1,106 +0,0 @@
-import 'package:beacon/Bloc/core/constants/location.dart';
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/domain/entities/beacon/beacon_entity.dart';
-import 'package:beacon/Bloc/domain/usecase/group_usecase.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:geolocator/geolocator.dart';
-
-abstract class GroupState {}
-
-class ShrimmerGroupState extends GroupState {}
-
-class GroupLoadingState extends GroupState {}
-
-class GroupErrorState extends GroupState {
- final String error;
-
- GroupErrorState({required this.error});
-}
-
-class GroupReloadState extends GroupState {
- List? beacons;
- BeaconEntity? beacon;
-
- GroupReloadState({this.beacon, this.beacons});
-}
-
-class GroupCubit extends Cubit {
- final GroupUseCase _groupUseCase;
- GroupCubit(this._groupUseCase) : super(ShrimmerGroupState());
-
- int page = 1;
- int pageSize = 4;
- bool isLoadingMore = false;
- bool isCompletelyFetched = false;
- List _beacons = [];
- List get beacons => _beacons;
- Position? position;
-
- Future createHike(String title, int startsAt, int expiresAt, String lat,
- String lon, String groupID) async {
- emit(GroupLoadingState());
- final state = await _groupUseCase.createHike(
- title, startsAt, expiresAt, lat, lon, groupID);
-
- if (state is DataFailed) {
- emit(GroupErrorState(error: state.error!));
- } else {
- BeaconEntity? newHike = state.data;
- newHike != null ? _beacons.insert(0, newHike) : null;
- emit(GroupReloadState());
- }
- }
-
- Future joinHike(String shortcode) async {
- emit(GroupLoadingState());
- final state = await _groupUseCase.joinHike(shortcode);
- if (state is DataFailed) {
- emit(GroupErrorState(error: state.error!));
- } else {
- BeaconEntity? newHike = state.data;
- newHike != null ? _beacons.insert(0, newHike) : null;
- emit(GroupReloadState());
- }
- }
-
- Future fetchGroupHikes(String groupID) async {
- if (isLoadingMore == true) return;
-
- if (page == 1) {
- emit(ShrimmerGroupState());
- }
-
- isLoadingMore = true;
- final state = await _groupUseCase.fetchHikes(groupID, page, pageSize);
-
- if (state is DataFailed) {
- isLoadingMore = false;
- emit(GroupErrorState(error: state.error!));
- } else {
- final hikes = state.data ?? [];
- isLoadingMore = false;
- page++;
- if (hikes.isEmpty) {
- isCompletelyFetched = true;
- emit(GroupReloadState());
- return;
- }
- for (var hike in hikes) {
- _beacons.add(hike);
- }
- emit(GroupReloadState());
- }
- }
-
- Future fetchPosition() async {
- position = await LocationService.getCurrentLocation();
- }
-
- clear() {
- page = 1;
- pageSize = 4;
- _beacons.clear();
- isCompletelyFetched = false;
- emit(ShrimmerGroupState());
- }
-}
diff --git a/lib/Bloc/presentation/cubit/home_cubit.dart b/lib/Bloc/presentation/cubit/home_cubit.dart
deleted file mode 100644
index 9202258b..00000000
--- a/lib/Bloc/presentation/cubit/home_cubit.dart
+++ /dev/null
@@ -1,102 +0,0 @@
-import 'dart:developer';
-import 'package:beacon/Bloc/core/resources/data_state.dart';
-import 'package:beacon/Bloc/domain/entities/group/group_entity.dart';
-import 'package:beacon/Bloc/domain/usecase/home_usecase.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-abstract class HomeState {}
-
-class InitialHomeState extends HomeState {}
-
-class ReloadState extends HomeState {}
-
-class ShrimmerState extends HomeState {}
-
-class LoadingMoreGroups extends HomeState {}
-
-class NewGroupLoadingState extends HomeState {}
-
-class ErrorHomeState extends HomeState {
- String error;
- ErrorHomeState({required this.error});
-}
-
-class HomeCubit extends Cubit {
- final HomeUseCase homeUseCase;
- HomeCubit({required this.homeUseCase}) : super(InitialHomeState());
-
- int page = 1;
- int pageSize = 4;
- bool isLoadingMore = false;
- bool isCompletelyFetched = false;
- List _totalGroups = [];
- List get totalGroups => _totalGroups;
-
- Future createGroup(String title) async {
- emit(NewGroupLoadingState());
- final dataState = await homeUseCase.createGroup(title);
- if (dataState is DataFailed) {
- emit(ErrorHomeState(error: dataState.error!));
- } else {
- GroupEntity? group = dataState.data;
- group != null ? _totalGroups.insert(0, group) : null;
- emit(ReloadState());
- }
- }
-
- Future joinGroup(String shortCode) async {
- emit(NewGroupLoadingState());
- DataState state = await homeUseCase.joinGroup(shortCode);
-
- if (state is DataFailed) {
- emit(ErrorHomeState(error: state.error!));
- } else {
- GroupEntity? group = state.data;
- group != null ? _totalGroups.insert(0, group) : null;
- emit(ReloadState());
- }
- }
-
- Future fetchUserGroups() async {
- // if already loading then return
- if (isCompletelyFetched == true || isLoadingMore == true) return;
-
- if (page != 1) log('fetching next set of groups');
-
- if (page == 1) {
- emit(ShrimmerState());
- } else {
- isLoadingMore = true;
- emit(LoadingMoreGroups());
- }
-
- DataState> state =
- await homeUseCase.groups(page, pageSize);
-
- if (state is DataFailed) {
- isLoadingMore = false;
- emit(ErrorHomeState(error: state.error!));
- } else {
- List newGroups = state.data ?? [];
- if (newGroups.isEmpty) {
- isCompletelyFetched = true;
- emit(ReloadState());
- return;
- }
- for (var newGroup in newGroups) {
- _totalGroups.add(newGroup);
- }
- page++;
- isLoadingMore = false;
- emit(ReloadState());
- }
- }
-
- clear() {
- page = 1;
- isLoadingMore = false;
- isCompletelyFetched = false;
- _totalGroups.clear();
- emit(InitialHomeState());
- }
-}
diff --git a/lib/Bloc/presentation/screens/group_screen.dart b/lib/Bloc/presentation/screens/group_screen.dart
deleted file mode 100644
index d50053c6..00000000
--- a/lib/Bloc/presentation/screens/group_screen.dart
+++ /dev/null
@@ -1,379 +0,0 @@
-import 'package:auto_route/auto_route.dart';
-import 'package:beacon/Bloc/domain/entities/group/group_entity.dart';
-import 'package:beacon/Bloc/presentation/cubit/group_cubit.dart';
-import 'package:beacon/Bloc/presentation/widgets/create_join_dialog.dart';
-import 'package:beacon/old/components/beacon_card.dart';
-import 'package:beacon/old/components/hike_button.dart';
-import 'package:beacon/old/components/loading_screen.dart';
-import 'package:beacon/old/components/shape_painter.dart';
-import 'package:beacon/locator.dart';
-import 'package:beacon/old/components/models/beacon/beacon.dart';
-import 'package:beacon/old/components/utilities/constants.dart';
-import 'package:beacon/router.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
-import 'package:sizer/sizer.dart';
-
-@RoutePage()
-class GroupScreen extends StatefulWidget {
- final GroupEntity group;
- GroupScreen(this.group) : super();
-
- @override
- _GroupScreenState createState() => _GroupScreenState();
-}
-
-class _GroupScreenState extends State
- with TickerProviderStateMixin {
- late List fetchingUserBeacons;
- late List fetchingNearbyBeacons;
-
- late GroupCubit _groupCubit;
- late ScrollController _scrollController;
-
- @override
- void initState() {
- _scrollController = ScrollController();
- _scrollController.addListener(_listener);
- _groupCubit = context.read();
- _groupCubit.position == null ? _groupCubit.fetchPosition() : null;
- _groupCubit.fetchGroupHikes(widget.group.id!);
- super.initState();
- }
-
- _listener() {
- if (_scrollController.position.pixels ==
- _scrollController.position.maxScrollExtent) {
- if (_groupCubit.isCompletelyFetched == true) {
- return;
- }
- _groupCubit.fetchGroupHikes(widget.group.id!);
- }
- }
-
- @override
- void dispose() {
- _groupCubit.clear();
- super.dispose();
- }
-
- @override
- Widget build(BuildContext context) {
- TabController tabController = new TabController(length: 2, vsync: this);
- return Scaffold(
- resizeToAvoidBottomInset: false,
- body: SafeArea(
- child: BlocConsumer(
- listener: (context, state) {
- if (state is GroupErrorState) {
- utils.showSnackBar(state.error, context);
- }
- },
- builder: (context, state) {
- return ModalProgressHUD(
- progressIndicator: const LoadingScreen(),
- inAsyncCall: (state is GroupLoadingState) ? true : false,
- child: Stack(
- children: [
- CustomPaint(
- size: Size(MediaQuery.of(context).size.width,
- MediaQuery.of(context).size.height - 200),
- painter: ShapePainter(),
- ),
- Align(
- alignment: Alignment(-0.7, -0.95),
- child: Container(
- width: MediaQuery.of(context).size.width * 0.6,
- child: Text(
- 'Welcome to Group ' + widget.group.title!,
- textAlign: TextAlign.center,
- style: TextStyle(
- fontSize: 25,
- color: Colors.white,
- ),
- ),
- ),
- ),
- Align(
- alignment: Alignment(0.9, -0.8),
- child: FloatingActionButton(
- onPressed: () => showDialog(
- context: context,
- builder: (context) => AlertDialog(
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(10.0),
- ),
- // actionsAlignment:
- // MainAxisAlignment.spaceEvenly,
- title: Text(
- localApi.userModel.isGuest!
- ? 'Create Account'
- : 'Logout',
- style:
- TextStyle(fontSize: 25, color: kYellow),
- ),
- content: Text(
- localApi.userModel.isGuest!
- ? 'Would you like to create an account?'
- : 'Are you sure you wanna logout?',
- style: TextStyle(fontSize: 16, color: kBlack),
- ),
- actions: [
- HikeButton(
- buttonHeight: 2.5.h,
- buttonWidth: 8.w,
- onTap: () =>
- Navigator.of(context).pop(false),
- text: 'No',
- textSize: 18.0,
- ),
- HikeButton(
- buttonHeight: 2.5.h,
- buttonWidth: 8.w,
- onTap: () async {
- AutoRouter.of(context).maybePop();
- AutoRouter.of(context).pushAndPopUntil(
- AuthScreenRoute(),
- predicate: (route) => true,
- );
- await localApi.deleteUser();
- },
- text: 'Yes',
- textSize: 18.0,
- ),
- ],
- )),
- backgroundColor: kYellow,
- child: localApi.userModel.isGuest!
- ? Icon(Icons.person)
- : Icon(Icons.logout),
- ),
- ),
- Padding(
- padding: EdgeInsets.fromLTRB(4.w, 25.h, 4.w, 5),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- mainAxisSize: MainAxisSize.max,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- Container(
- width: 45.w,
- child: HikeButton(
- buttonWidth: homebwidth,
- buttonHeight: homebheight - 2,
- text: 'Create Hike',
- textColor: Colors.white,
- borderColor: Colors.white,
- buttonColor: kYellow,
- onTap: () {
- CreateJoinBeaconDialog.createHikeDialog(
- context, widget.group.id, _groupCubit);
- },
- ),
- ),
- SizedBox(
- width: 1.w,
- ),
- Container(
- width: 45.w,
- child: HikeButton(
- buttonWidth: homebwidth,
- buttonHeight: homebheight - 2,
- text: 'Join a Hike',
- textColor: kYellow,
- borderColor: kYellow,
- buttonColor: Colors.white,
- onTap: () async {
- CreateJoinBeaconDialog.joinBeaconDialog(
- context, _groupCubit);
- },
- ),
- ),
- ],
- ),
- ),
- Column(
- mainAxisAlignment: MainAxisAlignment.end,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- Container(
- height: MediaQuery.of(context).size.height * 0.565,
- margin: EdgeInsets.only(top: 20),
- decoration: BoxDecoration(
- color: kLightBlue,
- borderRadius: BorderRadius.only(
- topLeft: const Radius.circular(50.0),
- topRight: const Radius.circular(50.0),
- ),
- ),
- child: Column(
- children: [
- TabBar(
- indicatorSize: TabBarIndicatorSize.tab,
- indicatorColor: kBlue,
- labelColor: kBlack,
- tabs: [
- Tab(text: 'Your Beacons'),
- Tab(text: 'Nearby Beacons'),
- ],
- controller: tabController,
- ),
- Expanded(
- child: TabBarView(
- controller: tabController,
- children: [
- _groupBeacons(),
- _nearByBeacons()
- ],
- ),
- )
- ],
- ))
- ],
- ),
- ],
- ),
- );
- },
- ),
- ),
- );
- }
-
- Widget _groupBeacons() {
- return Padding(
- padding: EdgeInsets.symmetric(horizontal: 2.0),
- child: BlocBuilder(
- builder: (context, state) {
- if (state is ShrimmerGroupState) {
- return Center(
- child: BeaconCustomWidgets.getPlaceholder(),
- );
- }
- final beacons = _groupCubit.beacons;
-
- return Container(
- alignment: Alignment.center,
- child: beacons.length == 0
- ? SingleChildScrollView(
- physics: AlwaysScrollableScrollPhysics(),
- child: Column(
- children: [
- Text(
- 'You haven\'t joined or created any beacon yet',
- textAlign: TextAlign.center,
- style: TextStyle(color: kBlack, fontSize: 20),
- ),
- SizedBox(
- height: 2.h,
- ),
- RichText(
- text: TextSpan(
- style: TextStyle(color: kBlack, fontSize: 20),
- children: [
- TextSpan(
- text: 'Join',
- style:
- TextStyle(fontWeight: FontWeight.bold)),
- TextSpan(text: ' a Hike or '),
- TextSpan(
- text: 'Create',
- style:
- TextStyle(fontWeight: FontWeight.bold)),
- TextSpan(text: ' a new one! '),
- ],
- ),
- ),
- ],
- ),
- )
- : ListView.builder(
- controller: _scrollController,
- physics: AlwaysScrollableScrollPhysics(),
- scrollDirection: Axis.vertical,
- itemCount: beacons.length,
- padding: EdgeInsets.all(8),
- itemBuilder: (context, index) {
- if (index == beacons.length) {
- return _groupCubit.isLoadingMore
- ? Center(
- child: LinearProgressIndicator(
- color: kBlue,
- ))
- : SizedBox.shrink();
- }
- return BeaconCustomWidgets.getBeaconCard(
- context, beacons[index]);
- },
- ));
- },
- ),
- );
- }
-
- Widget _nearByBeacons() {
- return Padding(
- padding: EdgeInsets.symmetric(horizontal: 2),
- child: BlocBuilder(
- builder: (context, state) {
- if (state is ShrimmerGroupState) {
- return Center(
- child: BeaconCustomWidgets.getPlaceholder(),
- );
- }
- final beacons = _groupCubit.beacons;
-
- return Container(
- alignment: Alignment.center,
- child: beacons.length == 0
- ? SingleChildScrollView(
- physics: AlwaysScrollableScrollPhysics(),
- child: Column(
- children: [
- Text(
- 'You haven\'t joined or created any beacon yet',
- textAlign: TextAlign.center,
- style: TextStyle(color: kBlack, fontSize: 20),
- ),
- SizedBox(
- height: 2.h,
- ),
- RichText(
- text: TextSpan(
- // textAlign:
- // TextAlign
- // .center,
- style: TextStyle(color: kBlack, fontSize: 20),
- children: [
- TextSpan(
- text: 'Join',
- style:
- TextStyle(fontWeight: FontWeight.bold)),
- TextSpan(text: ' a Hike or '),
- TextSpan(
- text: 'Create',
- style:
- TextStyle(fontWeight: FontWeight.bold)),
- TextSpan(text: ' a new one! '),
- ],
- ),
- ),
- ],
- ),
- )
- : ListView.builder(
- physics: AlwaysScrollableScrollPhysics(),
- scrollDirection: Axis.vertical,
- itemCount: beacons.length,
- padding: EdgeInsets.all(8),
- itemBuilder: (context, index) {
- return BeaconCustomWidgets.getBeaconCard(
- context, beacons[index]);
- },
- ));
- },
- ),
- );
- }
-}
diff --git a/lib/Bloc/presentation/screens/hike_screen.dart b/lib/Bloc/presentation/screens/hike_screen.dart
deleted file mode 100644
index e622c815..00000000
--- a/lib/Bloc/presentation/screens/hike_screen.dart
+++ /dev/null
@@ -1,229 +0,0 @@
-import 'package:auto_route/auto_route.dart';
-import 'package:beacon/old/components/loading_screen.dart';
-import 'package:beacon/locator.dart';
-import 'package:beacon/old/components/view_model/hike_screen_model.dart';
-import 'package:beacon/old/components/views/base_view.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_animarker/flutter_map_marker_animation.dart';
-import 'package:google_maps_flutter/google_maps_flutter.dart';
-import 'package:intl/intl.dart';
-
-import 'package:beacon/old/components/hike_screen_widget.dart';
-import 'package:beacon/old/components/models/beacon/beacon.dart';
-
-import 'package:beacon/old/components/utilities/constants.dart';
-import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
-
-import 'package:sizer/sizer.dart';
-import 'package:sliding_up_panel/sliding_up_panel.dart';
-
-@RoutePage()
-class HikeScreen extends StatefulWidget {
- final Beacon? beacon;
- final bool? isLeader;
- HikeScreen(this.beacon, {this.isLeader});
- @override
- _HikeScreenState createState() => _HikeScreenState();
-}
-
-class _HikeScreenState extends State {
- late double screenHeight, screenWidth;
- @override
- Widget build(BuildContext context) {
- screenHeight = MediaQuery.of(context).size.height;
- screenWidth = MediaQuery.of(context).size.width;
- return BaseView(
- onModelReady: (m) {
- m.initialise(widget.beacon!, widget.isLeader);
- },
- builder: (ctx, model, child) {
- if (!model.modelIsReady) {
- return Scaffold(
- body: Center(
- child: LoadingScreen(),
- ),
- );
- }
- // ignore: deprecated_member_use
- return WillPopScope(
- onWillPop: () => model.onWillPop(context),
- child: Scaffold(
- body: SafeArea(
- child: ModalProgressHUD(
- inAsyncCall: model.isGeneratingLink || model.isBusy,
- child: SlidingUpPanel(
- maxHeight: 60.h,
- minHeight: 20.h,
- borderRadius: BorderRadius.only(
- topRight: Radius.circular(10),
- topLeft: Radius.circular(10),
- ),
- controller: model.panelController,
- collapsed: Container(
- decoration: BoxDecoration(
- color: kBlue,
- borderRadius: BorderRadius.only(
- topRight: Radius.circular(10),
- topLeft: Radius.circular(10),
- ),
- ),
- child: Column(
- children: [
- SizedBox(
- height: 1.5.h,
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Container(
- width: 65,
- height: 5,
- decoration: BoxDecoration(
- color: Colors.grey[300],
- borderRadius: BorderRadius.all(
- Radius.circular(12.0),
- ),
- ),
- ),
- ],
- ),
- SizedBox(
- height: 1.5.h,
- ),
- Container(
- width: double.infinity,
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 15),
- child: RichText(
- text: TextSpan(
- style: TextStyle(fontWeight: FontWeight.bold),
- children: [
- TextSpan(
- text: model.isBeaconExpired
- ? 'Beacon has been expired\n'
- : 'Beacon expiring at ${widget.beacon!.expiresAt == null ? '' : DateFormat("hh:mm a, d/M/y").format(DateTime.fromMillisecondsSinceEpoch(widget.beacon!.expiresAt!)).toString()}\n',
- style: TextStyle(fontSize: 18),
- ),
- TextSpan(
- text:
- 'Beacon holder at: ${model.address}\n',
- style: TextStyle(fontSize: 14),
- ),
- TextSpan(
- text:
- 'Total Followers: ${model.hikers.length - 1} (Swipe up to view the list of followers)\n',
- style: TextStyle(fontSize: 12),
- ),
- TextSpan(
- text: model.isBeaconExpired
- ? ''
- : 'Share this passkey to add user: ${widget.beacon!.shortcode}\n',
- style: TextStyle(fontSize: 12),
- ),
- ],
- ),
- ),
- ),
- height: 15.h,
- ),
- ],
- ),
- ),
- panel: HikeScreenWidget.panel(
- model.scrollController, model, context, widget.isLeader!),
- body: Stack(
- alignment: Alignment.topCenter,
- children: [
- Animarker(
- rippleColor: Colors.redAccent,
- rippleRadius: 0.01,
- useRotation: true,
- mapId: model.mapController.future.then(
- (value) => value.mapId,
- ),
- markers: model.markers.toSet(),
- // child: Text('hello'),
- child: GoogleMap(
- compassEnabled: true,
- mapType: MapType.terrain,
- polylines: model.polylines,
- initialCameraPosition: CameraPosition(
- target: LatLng(
- double.parse(widget.beacon!.location!.lat!),
- double.parse(widget.beacon!.location!.lon!),
- ),
- zoom: CAMERA_ZOOM,
- tilt: CAMERA_TILT,
- bearing: CAMERA_BEARING),
- onMapCreated: (GoogleMapController controller) {
- setState(() {
- model.mapController.complete(controller);
- });
- // setPolyline();
- },
- onTap: (loc) async {
- // if (model.panelController.isPanelOpen)
- // model.panelController.close();
- // else {
- // String? title;
- // HikeScreenWidget
- // .showCreateLandMarkDialogueDialog(
- // context,
- // model.landmarkFormKey,
- // title,
- // loc,
- // model.createLandmark,
-
- // );
- // }
- }),
- ),
- Align(
- alignment: Alignment(0.9, -0.98),
- child: model.isBeaconExpired
- ? Container()
- : HikeScreenWidget.shareButton(
- context, widget.beacon!.shortcode)),
- Align(
- alignment: Alignment(-0.9, -0.98),
- child: FloatingActionButton(
- onPressed: () {
- navigationService!.pop();
- },
- backgroundColor: kYellow,
- child: Icon(
- Icons.arrow_back,
- size: 35,
- color: Colors.white,
- ),
- ),
- ),
- if (!model.isBeaconExpired)
- //show the routeSharebutton only when beacon is active(?) and mapcontroller is ready.
- Align(
- alignment: screenHeight > 800
- ? Alignment(0.9, -0.8)
- : Alignment(0.9, -0.77),
- child: AnimatedOpacity(
- duration: Duration(milliseconds: 500),
- opacity:
- model.mapController.isCompleted ? 1.0 : 0.0,
- child: HikeScreenWidget.shareRouteButton(context,
- model.beacon, model.mapController, model.route),
- ),
- ),
- ],
- ),
- ),
- ),
- ),
- ),
- );
- },
- );
- }
-
- // void relayBeacon(User newHolder) {
- // Fluttertoast.showToast(msg: 'Beacon handed over to $newHolder');
- // }
-}
diff --git a/lib/Bloc/presentation/screens/splash_screen.dart b/lib/Bloc/presentation/screens/splash_screen.dart
deleted file mode 100644
index 0d7764a8..00000000
--- a/lib/Bloc/presentation/screens/splash_screen.dart
+++ /dev/null
@@ -1,58 +0,0 @@
-import 'package:auto_route/auto_route.dart';
-import 'package:beacon/Bloc/domain/usecase/auth_usecase.dart';
-import 'package:flutter/material.dart';
-import 'package:beacon/locator.dart';
-import '../../../old/components/loading_screen.dart';
-
-@RoutePage()
-class SplashScreen extends StatefulWidget {
- const SplashScreen({super.key});
-
- @override
- _SplashScreenState createState() => _SplashScreenState();
-}
-
-class _SplashScreenState extends State {
- bool isCheckingUrl = false;
-
- @override
- void initState() {
- _handleNavigation();
- super.initState();
- }
-
- _handleNavigation() async {
- await localApi.init();
- bool? isLoggedIn = await localApi.userloggedIn();
- final authUseCase = locator();
-
- if (isLoggedIn == true) {
- bool isConnected = await utils.checkInternetConnectivity();
- if (isConnected) {
- final userInfo = await authUseCase.getUserInfoUseCase();
- if (userInfo.data != null) {
- AutoRouter.of(context).replaceNamed('/home');
- } else {
- AutoRouter.of(context).replaceNamed('/auth');
- }
- } else {
- AutoRouter.of(context).replaceNamed('/home');
- }
- } else {
- AutoRouter.of(context).replaceNamed('/auth');
- }
- }
-
- @override
- void dispose() {
- super.dispose();
- }
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- key: const Key('SplashScreenScaffold'),
- body: LoadingScreen(),
- );
- }
-}
diff --git a/lib/Bloc/config/enviornment_config.dart b/lib/config/enviornment_config.dart
similarity index 100%
rename from lib/Bloc/config/enviornment_config.dart
rename to lib/config/enviornment_config.dart
diff --git a/lib/config/graphql_config.dart b/lib/config/graphql_config.dart
new file mode 100644
index 00000000..924b1087
--- /dev/null
+++ b/lib/config/graphql_config.dart
@@ -0,0 +1,75 @@
+// import 'dart:async';
+// import 'package:beacon/config/enviornment_config.dart';
+// import 'package:beacon/locator.dart';
+// import 'package:graphql_flutter/graphql_flutter.dart';
+
+import 'package:beacon/config/enviornment_config.dart';
+import 'package:beacon/locator.dart';
+import 'package:graphql_flutter/graphql_flutter.dart';
+
+class GraphQLConfig {
+ static String? token;
+ WebSocketLink? _webSocketLink;
+ static final HttpLink httpLink = HttpLink(
+ EnvironmentConfig.httpEndpoint!,
+ );
+
+ Future _loadAuthLink() async {
+ // no need to load token, it will get load when _loadWebSocketLink
+ return AuthLink(getToken: () async => token);
+ }
+
+ Future _loadWebSocketLink() async {
+ await _getToken();
+ _webSocketLink = WebSocketLink(EnvironmentConfig.websocketEndpoint!,
+ config: SocketClientConfig(
+ autoReconnect: true,
+ initialPayload: {"Authorization": token},
+ ));
+
+ return _webSocketLink!;
+ }
+
+ _getToken() async {
+ await localApi.init();
+ await localApi.userloggedIn();
+ token = localApi.userModel.authToken;
+ return true;
+ }
+
+// // for non auth clients
+ GraphQLClient clientToQuery() {
+ return GraphQLClient(
+ cache: GraphQLCache(),
+ link: httpLink,
+ );
+ }
+
+// // for auth clients
+ Future authClient() async {
+ await _getToken();
+ final AuthLink authLink = AuthLink(getToken: () async => '$token');
+ final Link finalAuthLink = authLink.concat(httpLink);
+ return GraphQLClient(
+ cache: GraphQLCache(partialDataPolicy: PartialDataCachePolicy.accept),
+ link: finalAuthLink,
+ );
+ }
+
+ // for subscription
+ Future graphQlClient() async {
+ final websocketLink = await _loadWebSocketLink();
+ final authLink = await _loadAuthLink();
+
+ return GraphQLClient(
+ cache: GraphQLCache(
+ partialDataPolicy: PartialDataCachePolicy.acceptForOptimisticData,
+ ),
+ link: Link.split(
+ (request) => request.isSubscription,
+ websocketLink,
+ authLink.concat(httpLink),
+ ),
+ );
+ }
+}
diff --git a/lib/old/components/services/local_notification.dart b/lib/config/local_notification.dart
similarity index 58%
rename from lib/old/components/services/local_notification.dart
rename to lib/config/local_notification.dart
index d6a30906..99bf4cb3 100644
--- a/lib/old/components/services/local_notification.dart
+++ b/lib/config/local_notification.dart
@@ -1,6 +1,10 @@
+import 'dart:developer';
+
+import 'package:beacon/config/router/router.dart';
+import 'package:beacon/core/resources/data_state.dart';
+import 'package:beacon/domain/entities/beacon/beacon_entity.dart';
+import 'package:beacon/domain/usecase/hike_usecase.dart';
import 'package:beacon/locator.dart';
-import 'package:beacon/old/components/models/beacon/beacon.dart';
-import 'package:beacon/Bloc/presentation/screens/hike_screen.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;
@@ -32,24 +36,36 @@ class LocalNotification {
);
}
- Future onSelectNotification(notificationResponse) async {
- if (notificationResponse != null) {
- Beacon beacon = await (databaseFunctions!
- .fetchBeaconInfo(notificationResponse.payload) as Future);
- bool isLeader = beacon.leader!.id == userConfig!.currentUser!.id;
- navigationService!.pushScreen('/hikeScreen',
- arguments: HikeScreen(beacon, isLeader: isLeader));
+ Future onSelectNotification(
+ NotificationResponse notificationResponse) async {
+ String beaconId = notificationResponse.payload!;
+
+ var hikeUseCase = locator();
+
+ // Fetch beacon details
+ final dataState = await hikeUseCase.fetchBeaconDetails(beaconId);
+ if (dataState is DataSuccess) {
+ var beacon = dataState.data;
+ bool isLeader = beacon!.leader!.id == localApi.userModel.id;
+ appRouter.push(HikeScreenRoute(beacon: beacon, isLeader: isLeader));
}
- return;
}
Future deleteNotification() async {
await flutterLocalNotificationsPlugin.cancelAll();
}
- Future scheduleNotification(Beacon beacon) async {
- var scheduledDate1 = await tz.TZDateTime.from(
- DateTime.fromMillisecondsSinceEpoch(beacon.startsAt!), tz.local);
+ Future scheduleNotification(BeaconEntity beacon) async {
+ var scheduledDate1 =
+ tz.TZDateTime.fromMillisecondsSinceEpoch(tz.local, beacon.startsAt!);
+
+ // Check if scheduledDate1 is in the future
+ if (scheduledDate1.isBefore(tz.TZDateTime.now(tz.local))) {
+ log('Scheduled date is not in the future.');
+ return;
+ }
+
+ // Schedule the notification for the beacon start time
await flutterLocalNotificationsPlugin.zonedSchedule(
beacon.id.hashCode,
'Hike ' + beacon.title! + ' has started',
@@ -59,7 +75,6 @@ class LocalNotification {
android: AndroidNotificationDetails(
'channel id',
'channel name',
- // 'this is description',
playSound: true,
priority: Priority.high,
importance: Importance.high,
@@ -76,15 +91,11 @@ class LocalNotification {
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
payload: beacon.id,
);
- // We have to check if the hike is after 1 hour or not
- var scheduledDate2 = await tz.TZDateTime.from(
- DateTime.fromMillisecondsSinceEpoch(beacon.startsAt!),
- tz.local,
- ).subtract(Duration(hours: 1));
+ var scheduledDate2 = scheduledDate1.subtract(Duration(hours: 1));
- if (!scheduledDate2.isAfter(tz.TZDateTime.from(
- DateTime.fromMillisecondsSinceEpoch(beacon.startsAt!), tz.local))) {
+ if (scheduledDate2.isBefore(tz.TZDateTime.now(tz.local))) {
+ log('Reminder date is not in the future.');
return;
}
@@ -97,7 +108,6 @@ class LocalNotification {
android: AndroidNotificationDetails(
'channel id',
'channel name',
- // 'this is description',
playSound: true,
priority: Priority.high,
importance: Importance.high,
@@ -115,4 +125,34 @@ class LocalNotification {
payload: beacon.id,
);
}
+
+ Future> getPendingNotifications() async {
+ final pendingNotifications =
+ await flutterLocalNotificationsPlugin.pendingNotificationRequests();
+ return pendingNotifications;
+ }
+
+ Future showInstantNotification(String title, String body) async {
+ await flutterLocalNotificationsPlugin.show(
+ 0,
+ title,
+ body,
+ NotificationDetails(
+ android: AndroidNotificationDetails(
+ 'channel id',
+ 'channel name',
+ // 'this is description',
+ playSound: true,
+ priority: Priority.high,
+ importance: Importance.high,
+ ),
+ iOS: DarwinNotificationDetails(
+ presentAlert: true,
+ presentBadge: true,
+ presentSound: true,
+ badgeNumber: 1,
+ ),
+ ),
+ );
+ }
}
diff --git a/lib/config/pip_manager.dart b/lib/config/pip_manager.dart
new file mode 100644
index 00000000..4c0e8e8f
--- /dev/null
+++ b/lib/config/pip_manager.dart
@@ -0,0 +1,29 @@
+import 'package:flutter/services.dart';
+
+class PIPMode {
+ static const platform = MethodChannel("com.example.beacon/pip");
+
+ // static Future enterPIPMode() async {
+ // try {
+ // await platform.invokeMethod('enablePIPMode');
+ // } on PlatformException catch (e) {
+ // print("Failed to enter PIP mode: '${e.message}'.");
+ // }
+ // }
+
+ static Future disablePIPMode() async {
+ try {
+ await platform.invokeMethod('disablePIPMode');
+ } on PlatformException catch (e) {
+ print("Failed to enter PIP mode: '${e.message}'.");
+ }
+ }
+
+ static Future switchPIPMode() async {
+ try {
+ await platform.invokeMethod('switchPIPMode');
+ } on PlatformException catch (e) {
+ print("Failed to enter PIP mode: '${e.message}'.");
+ }
+ }
+}
diff --git a/lib/config/router/router.dart b/lib/config/router/router.dart
new file mode 100644
index 00000000..7ff17774
--- /dev/null
+++ b/lib/config/router/router.dart
@@ -0,0 +1,29 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:beacon/domain/entities/group/group_entity.dart';
+import 'package:beacon/presentation/auth/verfication_screen.dart';
+import 'package:beacon/presentation/splash/splash_screen.dart';
+import 'package:beacon/presentation/home/home_screen.dart';
+import 'package:flutter/material.dart';
+import 'package:beacon/presentation/auth/auth_screen.dart';
+import 'package:beacon/presentation/group/group_screen.dart';
+import 'package:beacon/presentation/hike/hike_screen.dart';
+import 'package:beacon/domain/entities/beacon/beacon_entity.dart';
+part 'router.gr.dart';
+
+@AutoRouterConfig(replaceInRouteName: 'Route')
+class AppRouter extends _$AppRouter {
+ @override
+ List get routes => [
+ AutoRoute(page: SplashScreenRoute.page, initial: true, path: '/'),
+ AutoRoute(page: AuthScreenRoute.page, path: '/auth'),
+ AutoRoute(page: HomeScreenRoute.page, path: '/home'),
+ AutoRoute(
+ page: HikeScreenRoute.page,
+ path: '/hike/:hikeDetails',
+ ),
+ AutoRoute(page: GroupScreenRoute.page),
+ AutoRoute(
+ page: VerificationScreenRoute.page,
+ ),
+ ];
+}
diff --git a/lib/router.gr.dart b/lib/config/router/router.gr.dart
similarity index 81%
rename from lib/router.gr.dart
rename to lib/config/router/router.gr.dart
index bac583f4..994646b0 100644
--- a/lib/router.gr.dart
+++ b/lib/config/router/router.gr.dart
@@ -33,7 +33,8 @@ abstract class _$AppRouter extends RootStackRouter {
return AutoRoutePage(
routeData: routeData,
child: HikeScreen(
- args.beacon,
+ key: args.key,
+ beacon: args.beacon,
isLeader: args.isLeader,
),
);
@@ -50,6 +51,12 @@ abstract class _$AppRouter extends RootStackRouter {
child: const SplashScreen(),
);
},
+ VerificationScreenRoute.name: (routeData) {
+ return AutoRoutePage(
+ routeData: routeData,
+ child: const VerificationScreen(),
+ );
+ },
};
}
@@ -100,12 +107,14 @@ class GroupScreenRouteArgs {
/// [HikeScreen]
class HikeScreenRoute extends PageRouteInfo {
HikeScreenRoute({
- required Beacon? beacon,
- bool? isLeader,
+ Key? key,
+ required BeaconEntity beacon,
+ required bool? isLeader,
List? children,
}) : super(
HikeScreenRoute.name,
args: HikeScreenRouteArgs(
+ key: key,
beacon: beacon,
isLeader: isLeader,
),
@@ -120,17 +129,20 @@ class HikeScreenRoute extends PageRouteInfo {
class HikeScreenRouteArgs {
const HikeScreenRouteArgs({
+ this.key,
required this.beacon,
- this.isLeader,
+ required this.isLeader,
});
- final Beacon? beacon;
+ final Key? key;
+
+ final BeaconEntity beacon;
final bool? isLeader;
@override
String toString() {
- return 'HikeScreenRouteArgs{beacon: $beacon, isLeader: $isLeader}';
+ return 'HikeScreenRouteArgs{key: $key, beacon: $beacon, isLeader: $isLeader}';
}
}
@@ -161,3 +173,17 @@ class SplashScreenRoute extends PageRouteInfo {
static const PageInfo page = PageInfo(name);
}
+
+/// generated route for
+/// [VerificationScreen]
+class VerificationScreenRoute extends PageRouteInfo {
+ const VerificationScreenRoute({List? children})
+ : super(
+ VerificationScreenRoute.name,
+ initialChildren: children,
+ );
+
+ static const String name = 'VerificationScreenRoute';
+
+ static const PageInfo page = PageInfo(name);
+}
diff --git a/lib/config/service_location.dart b/lib/config/service_location.dart
new file mode 100644
index 00000000..8e0f6393
--- /dev/null
+++ b/lib/config/service_location.dart
@@ -0,0 +1,29 @@
+import 'package:location/location.dart';
+
+class ServiceLocation {
+ static LocationData? locationData;
+ Future getLocation() async {
+ Location location = new Location();
+
+ bool _serviceEnabled;
+ PermissionStatus _permissionGranted;
+
+ _serviceEnabled = await location.serviceEnabled();
+ if (!_serviceEnabled) {
+ _serviceEnabled = await location.requestService();
+ if (!_serviceEnabled) {
+ return;
+ }
+ }
+
+ _permissionGranted = await location.hasPermission();
+ if (_permissionGranted == PermissionStatus.denied) {
+ _permissionGranted = await location.requestPermission();
+ if (_permissionGranted != PermissionStatus.granted) {
+ return;
+ }
+ }
+
+ locationData = await location.getLocation();
+ }
+}
diff --git a/lib/Bloc/core/queries/auth.dart b/lib/core/queries/auth.dart
similarity index 61%
rename from lib/Bloc/core/queries/auth.dart
rename to lib/core/queries/auth.dart
index 1c44b5c3..ce67feeb 100644
--- a/lib/Bloc/core/queries/auth.dart
+++ b/lib/core/queries/auth.dart
@@ -12,6 +12,14 @@ class AuthQueries {
''';
}
+ String gAuth(String? name, String email) {
+ return '''
+ mutation{
+ oAuth(userInput: {email: "$email", name: "$name"})
+ }
+ ''';
+ }
+
String loginAsGuest(String? name) {
return '''
mutation{
@@ -24,6 +32,33 @@ class AuthQueries {
''';
}
+ String sendVerficationCode() {
+ return '''
+ mutation{
+ sendVerificationCode
+ }
+ ''';
+ }
+
+ String completeVerificationCode() {
+ return '''
+ mutation{
+ completeVerification{
+ _id
+ email
+ name
+ groups{
+ _id
+ }
+ isVerified
+ beacons{
+ _id
+ }
+ }
+ }
+ ''';
+ }
+
String loginUser(String email, String? password) {
return '''
mutation{
@@ -47,6 +82,7 @@ class AuthQueries {
_id
email
name
+ isVerified
groups{
_id
}
diff --git a/lib/Bloc/core/queries/beacon.dart b/lib/core/queries/beacon.dart
similarity index 58%
rename from lib/Bloc/core/queries/beacon.dart
rename to lib/core/queries/beacon.dart
index 5cef7678..ea2735f5 100644
--- a/lib/Bloc/core/queries/beacon.dart
+++ b/lib/core/queries/beacon.dart
@@ -1,6 +1,59 @@
+import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class BeaconQueries {
+ String filterBeacons(String groupId, String type) {
+ return '''query{
+ filterBeacons(id:"$groupId", type: "$type"){
+ _id
+ title
+ leader{
+ _id
+ name
+ }
+ startsAt
+ expiresAt
+ shortcode
+ }
+ }
+''';
+ }
+
+ String rescheduleHike(int newExpirestAt, int newStartsAt, String beaconId) {
+ return '''mutation{ rescheduleHike(newExpiresAt: $newExpirestAt, newStartsAt: $newStartsAt, beaconID: "$beaconId"){
+ _id
+ title
+ shortcode
+ leader {
+ _id
+ name
+ }
+ group{
+ _id
+ title
+ }
+ location{
+ lat
+ lon
+ }
+ followers {
+ _id
+ name
+ }
+ startsAt
+ expiresAt
+ }}''';
+ }
+
+ String deleteBeacon(String? id) {
+ return '''
+
+mutation{
+deleteBeacon(id: "$id")
+}
+''';
+ }
+
String changeLeader(String? beaconID, String? newLeaderID) {
return '''
mutation{
@@ -60,6 +113,10 @@ class BeaconQueries {
leader {
_id
name
+ email
+ beacons{
+ _id
+ }
}
group {
_id
@@ -87,7 +144,7 @@ class BeaconQueries {
''';
}
- String updateLeaderLoc(String? id, String lat, String lon) {
+ String updateBeaconLocation(String? id, String lat, String lon) {
return '''
mutation {
updateBeaconLocation(id: "$id", location: {lat: "$lat", lon:"$lon"}){
@@ -100,6 +157,19 @@ class BeaconQueries {
''';
}
+ String changeUserLocation(String? id, String lat, String lon) {
+ return '''
+ mutation {
+ updateUserLocation(id: "$id", location: {lat: "$lat", lon:"$lon"}){
+ location{
+ lat
+ lon
+ }
+ }
+ }
+ ''';
+ }
+
String addLandmark(String title, String lat, String lon, String id) {
return '''
mutation{
@@ -159,7 +229,12 @@ class BeaconQueries {
_id
title
leader{
+ _id
name
+ location{
+ lat
+ lon
+ }
}
group {
_id
@@ -174,16 +249,25 @@ class BeaconQueries {
}
}
landmarks{
+ _id
title
location{
lat
lon
}
+ createdBy{
+ _id
+ name
+ }
}
location{
lat
lon
}
+ route{
+ lat
+ lon
+ }
startsAt
expiresAt
shortcode
@@ -192,13 +276,30 @@ class BeaconQueries {
''';
}
- String fetchNearbyBeacons(String lat, String lon) {
+ String addRoute(String id, LatLng latlng) {
+ return '''
+ mutation{
+ addRoute(
+ id: "$id"
+ location:{
+ lat: "${latlng.latitude}",
+ lon: "${latlng.longitude}"
+ }
+ )
+ }
+ ''';
+ }
+
+ String fetchNearbyBeacons(String id, String lat, String lon, double radius) {
return '''
query {
- nearbyBeacons(location:{
+ nearbyBeacons(
+ id: "$id",
+ location:{
lat: "$lat",
lon: "$lon"
- }){
+ },
+ radius: $radius){
_id
title
shortcode
@@ -207,6 +308,7 @@ class BeaconQueries {
title
}
leader {
+ _id
name
location {
lat
@@ -223,13 +325,6 @@ class BeaconQueries {
}
startsAt
expiresAt
- landmarks {
- title
- location {
- lat
- lon
- }
- }
}
}
''';
@@ -257,6 +352,49 @@ class BeaconQueries {
}
''');
+ final joinleaveBeaconSubGql = gql(r'''
+ subscription StreamNewlyJoinedBeacons($id: ID!){
+ JoinLeaveBeacon(id: $id){
+ newfollower{
+ _id
+ name
+ email
+ }
+ inactiveuser{
+ _id
+ name
+ email
+ }
+ }
+ }
+ ''');
+
+ final beaconUpdateSubGql = gql(r'''
+ subscription StreamBeaconUpdate($id: ID!){
+ updateBeacon(id: $id){
+ user{
+ _id
+ name
+ email
+ location{
+ lat
+ lon
+ }
+ }
+
+ landmark{
+ _id
+ title
+ location{
+ lat
+ lon
+ }
+ }
+
+ }
+ }
+ ''');
+
String createLandmark(String? id, String lat, String lon, String? title) {
return '''
mutation{
@@ -267,13 +405,70 @@ class BeaconQueries {
},
beaconID:"$id")
{
+ _id
title
location{
lat
lon
}
+ createdBy{
+ _id
+ name
+ }
}
}
''';
}
+
+ String sos(String id) {
+ return '''
+ mutation{
+ sos( id:"$id"){
+ _id
+ name
+ email
+ location{
+ lat
+ lon
+ }
+ }
+ }
+ ''';
+ }
+
+ final locationUpdateGQL = gql(r'''
+ subscription StreamLocationUpdate($id: ID!){
+ beaconLocations(id: $id){
+
+ route{
+ lat
+ lon
+ }
+
+ updatedUser{
+ _id
+ name
+ location{
+ lat
+ lon
+ }
+ }
+
+ landmark{
+ _id
+ title
+ location{
+ lat
+ lon
+ }
+ createdBy{
+ _id
+ name
+ email
+ }
+ }
+
+ }
+ }
+ ''');
}
diff --git a/lib/Bloc/core/queries/group.dart b/lib/core/queries/group.dart
similarity index 57%
rename from lib/Bloc/core/queries/group.dart
rename to lib/core/queries/group.dart
index bc760734..06cea688 100644
--- a/lib/Bloc/core/queries/group.dart
+++ b/lib/core/queries/group.dart
@@ -3,25 +3,26 @@ import 'package:graphql_flutter/graphql_flutter.dart';
class GroupQueries {
String fetchUserGroups(int page, int pageSize) {
return '''
- query {
- groups(page: $page, pageSize: $pageSize) {
- _id
- title
- shortcode
- leader {
- _id
- name
- }
- members {
- _id
- name
- }
- beacons {
- _id
- }
+ query {
+ groups(page: $page, pageSize: $pageSize) {
+ _id
+ title
+ beacons{
+ _id
+ }
+ leader{
+ _id
+ name
}
+ members{
+ _id
+ name
+ }
+ shortcode
+ __typename
}
- ''';
+ }
+ ''';
}
String createGroup(String? title) {
@@ -86,8 +87,7 @@ class GroupQueries {
_id
name
}
- beacons
- {
+ beacons{
_id
title
shortcode
@@ -130,22 +130,6 @@ class GroupQueries {
beacons
{
_id
- title
- shortcode
- leader {
- _id
- name
- }
- location{
- lat
- lon
- }
- followers {
- _id
- name
- }
- startsAt
- expiresAt
}
}
}
@@ -182,6 +166,129 @@ query{
''';
}
+ String changeShortCode(String groupId) {
+ return '''
+ mutation{
+ changeShortcode(groupId: "$groupId"){
+ _id
+ title
+ beacons{
+ _id
+ }
+ leader{
+ _id
+ name
+ }
+ members{
+ _id
+ name
+ }
+ shortcode
+ __typename
+ }
+ }
+
+''';
+ }
+
+ final groupUpdateSubGql = gql(r'''
+ subscription groupUpdate($groupIds: [ID!]!) {
+ groupUpdate(groupIds: $groupIds) {
+ groupId
+
+ newUser{
+ _id
+ name
+ email
+ }
+
+ newBeacon{
+ _id
+ title
+ leader {
+ _id
+ name
+ email
+ }
+ followers {
+ _id
+ name
+ }
+ group{
+ _id
+ }
+ location {
+ lat
+ lon
+ }
+ shortcode
+ startsAt
+ expiresAt
+ }
+
+ deletedBeacon{
+ _id
+ title
+ leader {
+ _id
+ name
+ email
+ }
+ followers {
+ _id
+ name
+ }
+ group{
+ _id
+ }
+ location {
+ lat
+ lon
+ }
+ shortcode
+ startsAt
+ expiresAt
+ }
+
+ updatedBeacon{
+ _id
+ title
+ leader {
+ _id
+ name
+ email
+ }
+ followers {
+ _id
+ name
+ }
+ group{
+ _id
+ }
+ location {
+ lat
+ lon
+ }
+ shortcode
+ startsAt
+ expiresAt
+ }
+ }
+ }
+''');
+
+ String removeMember(String groupId, String memberId) {
+ return '''
+ mutation{
+ removeMember(groupId: "$groupId", memberId: "$memberId"){
+ _id
+ name
+ email
+ }
+ }
+ ''';
+ }
+
final groupJoinedSubGql = gql(r'''
subscription StreamNewlyJoinedGroups($id: ID!){
groupJoined(id: $id){
diff --git a/lib/Bloc/core/resources/data_state.dart b/lib/core/resources/data_state.dart
similarity index 100%
rename from lib/Bloc/core/resources/data_state.dart
rename to lib/core/resources/data_state.dart
diff --git a/lib/core/services/location_services.dart b/lib/core/services/location_services.dart
new file mode 100644
index 00000000..e8d1a8aa
--- /dev/null
+++ b/lib/core/services/location_services.dart
@@ -0,0 +1,65 @@
+import 'package:geolocator/geolocator.dart';
+import 'package:google_maps_flutter/google_maps_flutter.dart';
+
+class LocationService {
+ static final LocationService _instance = LocationService._internal();
+
+ LocationService._internal();
+
+ factory LocationService() {
+ return _instance;
+ }
+
+ Position? _currentPosition;
+ Position? get currentPosition => _currentPosition;
+
+ Future getCurrentLocation() async {
+ bool serviceEnabled;
+ LocationPermission permission;
+
+ serviceEnabled = await Geolocator.isLocationServiceEnabled();
+
+ if (!serviceEnabled) {
+ return Future.error('Location service is disabled.');
+ }
+
+ permission = await Geolocator.checkPermission();
+
+ if (permission == LocationPermission.denied) {
+ permission = await Geolocator.requestPermission();
+ if (permission == LocationPermission.denied) {
+ return Future.error('Location permission is denied');
+ }
+ }
+
+ if (permission == LocationPermission.deniedForever) {
+ return Future.error('Location permission is permanently denied.');
+ }
+
+ try {
+ Position location = await Geolocator.getCurrentPosition(
+ desiredAccuracy: LocationAccuracy.high);
+
+ _currentPosition = location;
+
+ return location;
+ } catch (e) {
+ return Future.error('Failed to get location: $e');
+ }
+ }
+
+ Future openSettings() async {
+ await Geolocator.openAppSettings();
+ }
+
+ Future calculateDistance(LatLng first, LatLng second) async {
+ double distanceInMeters = await Geolocator.distanceBetween(
+ first.latitude,
+ first.longitude,
+ second.latitude,
+ second.longitude,
+ );
+
+ return distanceInMeters;
+ }
+}
diff --git a/lib/Bloc/core/services/shared_prefrence_service.dart b/lib/core/services/shared_prefrence_service.dart
similarity index 80%
rename from lib/Bloc/core/services/shared_prefrence_service.dart
rename to lib/core/services/shared_prefrence_service.dart
index 9e91b816..af083a85 100644
--- a/lib/Bloc/core/services/shared_prefrence_service.dart
+++ b/lib/core/services/shared_prefrence_service.dart
@@ -2,8 +2,13 @@ import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreferenceService {
- SharedPreferenceService() {
- init();
+ static SharedPreferenceService _instance =
+ SharedPreferenceService._internal();
+
+ SharedPreferenceService._internal();
+
+ factory SharedPreferenceService() {
+ return _instance;
}
late SharedPreferences _prefs;
@@ -35,6 +40,6 @@ class SharedPreferenceService {
}
Future deleteData(String key) async {
- return await _prefs.remove('key');
+ return await _prefs.remove(key);
}
}
diff --git a/lib/old/components/utilities/constants.dart b/lib/core/utils/constants.dart
similarity index 67%
rename from lib/old/components/utilities/constants.dart
rename to lib/core/utils/constants.dart
index 8f272eaf..35de8fd7 100644
--- a/lib/old/components/utilities/constants.dart
+++ b/lib/core/utils/constants.dart
@@ -1,7 +1,5 @@
import 'package:flutter/material.dart';
-import 'package:geolocator/geolocator.dart';
-import 'package:google_maps_flutter/google_maps_flutter.dart';
-import 'package:sizer/sizer.dart';
+import 'package:responsive_sizer/responsive_sizer.dart';
const Color kYellow = Color(0xFFFDBB2C);
const Color kBlue = Color(0xFF222375);
@@ -28,31 +26,8 @@ const String otherError = "Other Errors";
const String logSuccess = "Successful Login";
class AppConstants {
- static Future getLocation() async {
- bool serviceEnabled;
- LocationPermission permission;
-
- serviceEnabled = await Geolocator.isLocationServiceEnabled();
- if (!serviceEnabled) {
- return Future.error('Location services are disabled.');
- }
-
- permission = await Geolocator.checkPermission();
- if (permission == LocationPermission.denied) {
- permission = await Geolocator.requestPermission();
- if (permission == LocationPermission.denied) {
- return Future.error('Location permissions are denied');
- }
- }
-
- if (permission == LocationPermission.deniedForever) {
- return Future.error(
- 'Location permissions are permanently denied, we cannot request permissions.');
- }
-
- Position position = await Geolocator.getCurrentPosition();
- return LatLng(position.latitude, position.longitude);
- }
+ static const _imagePath = 'images';
+ static const filterIconPath = '$_imagePath/filter_icon.png';
}
//routes
diff --git a/lib/Bloc/core/utils/utils.dart b/lib/core/utils/utils.dart
similarity index 60%
rename from lib/Bloc/core/utils/utils.dart
rename to lib/core/utils/utils.dart
index aa80bd5e..6b9021c8 100644
--- a/lib/Bloc/core/utils/utils.dart
+++ b/lib/core/utils/utils.dart
@@ -1,18 +1,33 @@
import 'dart:developer';
-import 'package:beacon/old/components/utilities/constants.dart';
+import 'package:beacon/core/utils/constants.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
+import 'package:gap/gap.dart';
import 'package:graphql/client.dart';
+import 'package:responsive_sizer/responsive_sizer.dart';
class Utils {
void showSnackBar(String message, BuildContext context,
- {Duration duration = const Duration(seconds: 2)}) {
+ {Duration duration = const Duration(seconds: 2),
+ bool icon = false,
+ bool top = false}) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
duration: duration,
- content: Text(
- message,
- style: TextStyle(color: Colors.black),
+ content: Row(
+ children: [
+ icon
+ ? Image.asset(
+ 'images/male_avatar.png',
+ height: 35,
+ )
+ : Container(),
+ icon ? Gap(20) : Container(),
+ Text(
+ message,
+ style: TextStyle(color: Colors.black, fontSize: 12),
+ )
+ ],
),
backgroundColor: kLightBlue.withOpacity(0.8),
shape: RoundedRectangleBorder(
@@ -20,6 +35,9 @@ class Utils {
Radius.circular(10),
),
),
+ margin: top
+ ? EdgeInsets.only(top: 0, right: 10, left: 10, bottom: 85.h)
+ : null,
behavior: SnackBarBehavior.floating,
elevation: 5,
),
@@ -50,30 +68,4 @@ class Utils {
}
return false;
}
-
- String? validateEmail(String? value) {
- final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
- if (value == null || value.isEmpty) {
- return 'Email address is required';
- } else if (!emailRegex.hasMatch(value)) {
- return 'Enter a valid email address';
- }
- return null; // Return null if the email is valid
- }
-
- String? validatePassword(String? value) {
- if (value == null || value.isEmpty) {
- return 'Password is required';
- } else if (value.length < 8) {
- return '8-digit password is required';
- }
- return null;
- }
-
- String? validateName(String? value) {
- if (value == null || value.isEmpty) {
- return 'Name is required';
- }
- return null;
- }
}
diff --git a/lib/core/utils/validators.dart b/lib/core/utils/validators.dart
new file mode 100644
index 00000000..4d62cbe7
--- /dev/null
+++ b/lib/core/utils/validators.dart
@@ -0,0 +1,166 @@
+import 'package:flutter/material.dart';
+
+class Validator {
+ static String? validateName(String? name) {
+ if (name != null && name.isEmpty) {
+ return "Name must not be left blank";
+ }
+ return null;
+ }
+
+ static String? validateRadius(String? radius) {
+ if (radius == null) {
+ return 'Radius can\'t be blank';
+ }
+ try {
+ double.parse(radius);
+
+ return null;
+ } catch (e) {
+ return 'Radius should be number';
+ }
+ }
+
+ static String? validateDate(String? date) {
+ if (date == null || date.isEmpty || date == '') {
+ return 'Date can\'t be empty';
+ }
+
+ DateTime parsedDate = DateTime.parse(date);
+ DateTime now = DateTime.now();
+
+ DateTime currentDate = DateTime(now.year, now.month, now.day);
+ DateTime onlyDate =
+ DateTime(parsedDate.year, parsedDate.month, parsedDate.day);
+
+ if (onlyDate.isBefore(currentDate)) {
+ return 'Please enter a valid date';
+ }
+
+ return null;
+ }
+
+ static String? validateStartTime(String? time, String date) {
+ DateTime parsedDate = DateTime.parse(date);
+ DateTime selectedDate =
+ DateTime(parsedDate.year, parsedDate.month, parsedDate.day);
+ DateTime now = DateTime.now();
+ DateTime currentDate = DateTime(now.year, now.month, now.day);
+
+ if (selectedDate.isAfter(currentDate)) {
+ return null;
+ }
+
+ if (time == null || time.isEmpty) {
+ return 'Please chose a start time';
+ }
+
+ RegExp timeRegex = RegExp(r'^([0-1]?[0-9]|2[0-3]):[0-5][0-9] (AM|PM)$');
+
+ if (!timeRegex.hasMatch(time)) {
+ return 'Invalid time format. Please enter time in hh:mm AM/PM format';
+ }
+
+ TimeOfDay enteredTime = _stringToTimeOfDay(time);
+
+ TimeOfDay currentTime = TimeOfDay.now();
+
+ int isValid = compareTimeOfDay(enteredTime, currentTime);
+
+ if (isValid == -1) {
+ return 'Please chose a valid time';
+ }
+
+ return null;
+ }
+
+ static int compareTimeOfDay(TimeOfDay time1, TimeOfDay time2) {
+ if (time1.hour < time2.hour) {
+ return -1;
+ } else if (time1.hour > time2.hour) {
+ return 1;
+ } else {
+ // If hours are the same, compare minutes
+ if (time1.minute < time2.minute) {
+ return -1;
+ } else if (time1.minute > time2.minute) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ static TimeOfDay _stringToTimeOfDay(String time) {
+ final numbers = time.split(' ');
+ final format = numbers[0].split(":");
+ final hour = int.parse(format[0]);
+ final minute = int.parse(format[1]);
+
+ return TimeOfDay(hour: hour, minute: minute);
+ }
+
+ static String? validateEmail(String? email) {
+ // If email is empty return.
+ if (email != null && email.isEmpty) {
+ return "Email must not be left blank";
+ }
+ const String pattern =
+ r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$";
+ final RegExp regex = RegExp(pattern);
+ if (email != null && !regex.hasMatch(email)) {
+ return 'Please enter a valid Email Address';
+ }
+ return null;
+ }
+
+ static String? validatePassword(String? password) {
+ // If password is empty return.
+ if (password != null && password.isEmpty) {
+ return "Password must not be left blank";
+ }
+ // const String pattern = r'^(?=.*?[0-9])(?=.*?[!@#\$&*%^~.]).{8,}$';
+ // final RegExp regExp = RegExp(pattern);
+
+ //Regex for no spaces allowed
+ const String noSpaces = r'^\S+$';
+ final RegExp noSpaceRegex = RegExp(noSpaces);
+
+ if (password!.length < 8) {
+ return "Must be of atleast 8 characters";
+ }
+ // if (!regExp.hasMatch(password)) {
+ // return "At least 1 number and symbol required";
+ // }
+ if (!noSpaceRegex.hasMatch(password)) {
+ return "Password must not contain spaces";
+ }
+ return null;
+ }
+
+ static String? validateBeaconTitle(String? title) {
+ if (title != null && title.isEmpty) {
+ return "Title must not be left blank";
+ }
+ return null;
+ }
+
+ static String? validatePasskey(String? passkey) {
+ if (passkey != null && passkey.isEmpty) {
+ return "Passkey must not be left blank";
+ }
+ const String pattern = r'[A-Z]+';
+ final RegExp regExp = RegExp(pattern);
+ if (!regExp.hasMatch(passkey!) || passkey.length != 6) {
+ return "Invalid passkey";
+ }
+ return null;
+ }
+
+ static String? validateDuration(String? duration) {
+ if (duration == null || duration.isEmpty || duration == '') {
+ return "Please enter duration";
+ }
+ return null;
+ }
+}
diff --git a/lib/Bloc/data/datasource/local/local_api.dart b/lib/data/datasource/local/local_api.dart
similarity index 85%
rename from lib/Bloc/data/datasource/local/local_api.dart
rename to lib/data/datasource/local/local_api.dart
index 6b27fce2..13ace147 100644
--- a/lib/Bloc/data/datasource/local/local_api.dart
+++ b/lib/data/datasource/local/local_api.dart
@@ -1,11 +1,11 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';
-import 'package:beacon/Bloc/data/models/beacon/beacon_model.dart';
-import 'package:beacon/Bloc/data/models/group/group_model.dart';
-import 'package:beacon/Bloc/data/models/landmark/landmark_model.dart';
-import 'package:beacon/Bloc/data/models/location/location_model.dart';
-import 'package:beacon/Bloc/data/models/user/user_model.dart';
+import 'package:beacon/data/models/beacon/beacon_model.dart';
+import 'package:beacon/data/models/group/group_model.dart';
+import 'package:beacon/data/models/landmark/landmark_model.dart';
+import 'package:beacon/data/models/location/location_model.dart';
+import 'package:beacon/data/models/user/user_model.dart';
import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart' as path_provider;
@@ -15,10 +15,12 @@ class LocalApi {
String beaconModelBox = 'beaconBox';
String locationModelBox = 'locationBox';
String landMarkModelBox = 'landMarkBox';
+ String nearbyBeaconModelBox = 'nearbybeaconBox';
late Box userBox;
late Box groupBox;
late Box beaconBox;
+ late Box nearbyBeaconBox;
late Box locationBox;
late Box landMarkbox;
@@ -52,6 +54,7 @@ class LocalApi {
userBox = await Hive.openBox(userModelbox);
groupBox = await Hive.openBox(groupModelBox);
beaconBox = await Hive.openBox(beaconModelBox);
+ nearbyBeaconBox = await Hive.openBox(nearbyBeaconModelBox);
locationBox = await Hive.openBox(locationModelBox);
landMarkbox = await Hive.openBox(landMarkModelBox);
} catch (e) {
@@ -159,6 +162,16 @@ class LocalApi {
}
}
+ Future savenearbyBeacons(BeaconModel beacon) async {
+ try {
+ await deleteBeacon(beacon.id);
+ await nearbyBeaconBox.put(beacon.id, beacon);
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }
+
Future deleteBeacon(String? beaconId) async {
try {
bool doesExist = await beaconBox.containsKey(beaconId);
diff --git a/lib/data/datasource/remote/remote_auth_api.dart b/lib/data/datasource/remote/remote_auth_api.dart
new file mode 100644
index 00000000..d2f8cb43
--- /dev/null
+++ b/lib/data/datasource/remote/remote_auth_api.dart
@@ -0,0 +1,245 @@
+import 'dart:async';
+import 'dart:developer';
+
+import 'package:beacon/core/queries/auth.dart';
+import 'package:beacon/core/resources/data_state.dart';
+import 'package:beacon/data/datasource/remote/remote_group_api.dart';
+import 'package:beacon/data/datasource/remote/remote_hike_api.dart';
+import 'package:beacon/data/datasource/remote/remote_home_api.dart';
+import 'package:beacon/data/models/user/user_model.dart';
+import 'package:beacon/domain/entities/user/user_entity.dart';
+import 'package:beacon/locator.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:graphql_flutter/graphql_flutter.dart';
+
+class RemoteAuthApi {
+ GraphQLClient clientNonAuth;
+ late GraphQLClient _authClient;
+
+ RemoteAuthApi(this._authClient, this.clientNonAuth);
+
+ void loadClient(GraphQLClient newClient) {
+ _authClient = newClient;
+ }
+
+ AuthQueries _authQueries = AuthQueries();
+
+ Future> fetchUserInfo() async {
+ final isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected)
+ return DataFailed('Beacon is trying to connect with internet...');
+
+ var _authClient = await graphqlConfig.authClient();
+ // api call
+ final result = await _authClient
+ .mutate(MutationOptions(document: gql(_authQueries.fetchUserInfo())));
+
+ if (result.data != null && result.isConcrete) {
+ final json = result.data!['me'];
+ final user = UserModel.fromJson(json);
+
+ final currentUser = await localApi.fetchUser();
+
+ // checking if user is login
+ if (currentUser == null) return DataFailed('Please login first');
+ final newUser = user.copyWithModel(
+ authToken: currentUser.authToken,
+ isGuest: user.email == '' ? true : false);
+
+ // saving user details locally
+ await localApi.saveUser(newUser);
+
+ // returning
+ return DataSuccess(newUser);
+ }
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future> register(
+ String name, String email, String password) async {
+ try {
+ final isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected)
+ return DataFailed('Beacon is trying to connect with internet...');
+
+ final result = await clientNonAuth.mutate(
+ MutationOptions(
+ document: gql(_authQueries.registerUser(name, email, password)),
+ ),
+ );
+
+ if (result.data != null && result.isConcrete) {
+ // LOGIN API CALL
+ final dataState = await login(email, password);
+ return dataState;
+ } else if (result.hasException) {
+ final message = encounteredExceptionOrError(result.exception!);
+ return DataFailed(message);
+ }
+
+ return DataFailed('An unexpected error occurred during registration.');
+ } catch (e) {
+ return DataFailed(e.toString());
+ }
+ }
+
+ Future> gAuth(String name, String email) async {
+ log('name: $name');
+ log('email: $email');
+
+ final isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Beacon is trying to connect with internet...');
+ }
+
+ final QueryResult result = await clientNonAuth.mutate(
+ MutationOptions(document: gql(_authQueries.gAuth(name, email))));
+
+ log(result.toString());
+
+ if (result.data != null && result.isConcrete) {
+ final token = "Bearer ${result.data!['oAuth']}";
+
+ UserModel? user;
+
+ user = UserModel(authToken: token, isGuest: false);
+
+ // storing auth token in hive
+ await localApi.saveUser(user);
+
+ // loading clients
+ final authClient = await graphqlConfig.authClient();
+ final subscriptionClient = await graphqlConfig.graphQlClient();
+ locator().loadClient(authClient);
+ locator().loadClient(authClient, subscriptionClient);
+ locator().loadClient(authClient, subscriptionClient);
+ locator().loadClient(authClient, subscriptionClient);
+
+ // fetching User Info
+
+ final dataState = await fetchUserInfo();
+
+ if (dataState is DataSuccess) {
+ final updatedUser = dataState.data!
+ .copyWithModel(authToken: user.authToken, isGuest: user.isGuest);
+
+ // saving locally
+ await localApi.saveUser(updatedUser);
+
+ return DataSuccess(updatedUser);
+ }
+ } else if (result.hasException) {
+ final message = encounteredExceptionOrError(result.exception!);
+
+ return DataFailed(message);
+ }
+
+ return DataFailed('An unexpected error occured.');
+ }
+
+ Future> login(String email, String password) async {
+ log('calling login function $email');
+ final isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Beacon is trying to connect with internet...');
+ }
+
+ final QueryResult result = await clientNonAuth.mutate(MutationOptions(
+ document: gql(_authQueries.loginUser(email, password))));
+
+ if (result.data != null && result.isConcrete) {
+ final token = "Bearer ${result.data!['login']}";
+
+ UserModel? user;
+
+ // if (email.isEmpty) {
+ // user = UserModel(authToken: token, isGuest: true);
+ // } else {
+ user = UserModel(authToken: token, isGuest: false);
+ // }
+
+ // storing auth token in hive
+ await localApi.saveUser(user);
+
+ // loading clients
+ final authClient = await graphqlConfig.authClient();
+ final subscriptionClient = await graphqlConfig.graphQlClient();
+ locator().loadClient(authClient);
+ locator().loadClient(authClient, subscriptionClient);
+ locator().loadClient(authClient, subscriptionClient);
+ locator().loadClient(authClient, subscriptionClient);
+
+ // fetching User Info
+
+ final dataState = await fetchUserInfo();
+
+ if (dataState is DataSuccess) {
+ final updatedUser = dataState.data!
+ .copyWithModel(authToken: user.authToken, isGuest: user.isGuest);
+
+ // saving locally
+ await localApi.saveUser(updatedUser);
+
+ return DataSuccess(updatedUser);
+ }
+ } else if (result.hasException) {
+ final message = encounteredExceptionOrError(result.exception!);
+
+ return DataFailed(message);
+ }
+
+ return DataFailed('An unexpected error occured.');
+ }
+
+ Future> sendVerificationCode() async {
+ final isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Beacon is trying to connect with internet...');
+ }
+
+ final QueryResult result = await _authClient.mutate(
+ MutationOptions(document: gql(_authQueries.sendVerficationCode())));
+
+ if (result.data != null && result.isConcrete) {
+ return DataSuccess(result.data!['sendVerificationCode'] as String);
+ }
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future> completeVerification() async {
+ final isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Beacon is trying to connect with internet...');
+ }
+
+ var authClient = await graphqlConfig.authClient();
+
+ final QueryResult result = await authClient.mutate(MutationOptions(
+ document: gql(_authQueries.completeVerificationCode())));
+
+ if (result.data != null && result.isConcrete) {
+ var user = UserModel.fromJson(result.data!['completeVerification']);
+ var currentUser = await localApi.fetchUser();
+ currentUser = currentUser!.copyWithModel(isVerified: user.isVerified);
+ await localApi.saveUser(currentUser);
+ return DataSuccess(user);
+ }
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ String encounteredExceptionOrError(OperationException exception) {
+ if (exception.linkException != null) {
+ debugPrint(exception.linkException.toString());
+ return 'Something went wrong';
+ } else {
+ return exception.graphqlErrors[0].message.toString();
+ }
+ }
+}
diff --git a/lib/data/datasource/remote/remote_group_api.dart b/lib/data/datasource/remote/remote_group_api.dart
new file mode 100644
index 00000000..f1d3a8d8
--- /dev/null
+++ b/lib/data/datasource/remote/remote_group_api.dart
@@ -0,0 +1,243 @@
+import 'dart:async';
+
+import 'package:beacon/core/queries/beacon.dart';
+import 'package:beacon/core/queries/group.dart';
+import 'package:beacon/core/resources/data_state.dart';
+import 'package:beacon/data/models/beacon/beacon_model.dart';
+import 'package:beacon/data/models/group/group_model.dart';
+import 'package:beacon/data/models/user/user_model.dart';
+import 'package:beacon/domain/entities/user/user_entity.dart';
+import 'package:beacon/locator.dart';
+import 'package:graphql_flutter/graphql_flutter.dart';
+
+class RemoteGroupApi {
+ late GraphQLClient _authClient;
+
+ RemoteGroupApi(this._authClient);
+
+ void loadClient(GraphQLClient authClient, GraphQLClient subscriptionClient) {
+ this._authClient = authClient;
+ }
+
+ final _groupqueries = GroupQueries();
+
+ final _beaconQueries = BeaconQueries();
+
+ Future>> fetchHikes(
+ String groupId, int page, int pageSize) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ GroupModel? group = await localApi.getGroup(groupId);
+
+ if (group != null && group.beacons != null) {
+ int condition = (page - 1) * pageSize + pageSize;
+ int beaconLen = group.beacons!.length;
+
+ if (condition > beaconLen) {
+ condition = beaconLen;
+ }
+
+ List beacons = [];
+
+ for (int i = (page - 1) * pageSize; i < condition; i++) {
+ BeaconModel? beaconModel =
+ await localApi.getBeacon(group.beacons![i]!.id);
+
+ beaconModel != null ? beacons.add(beaconModel) : null;
+ }
+
+ return DataSuccess(beacons);
+ }
+
+ return DataFailed('Please check your internet connection!');
+ }
+
+ final result = await _authClient.query(QueryOptions(
+ document: gql(_groupqueries.fetchHikes(groupId, page, pageSize)),
+ fetchPolicy: FetchPolicy.networkOnly));
+
+ if (result.data != null && result.isConcrete) {
+ List hikesJson = result.data!['beacons'];
+
+ List hikes = [];
+
+ for (var hikeJson in hikesJson) {
+ BeaconModel hike = BeaconModel.fromJson(hikeJson);
+ hikes.add(hike);
+ // storing beacon
+ await localApi.saveBeacon(hike);
+ }
+
+ return DataSuccess(hikes);
+ }
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future> createHike(String title, int startsAt,
+ int expiresAt, String lat, String lon, String groupID) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Please check your internet connection!');
+ }
+ final result = await _authClient.mutate(MutationOptions(
+ document: gql(_beaconQueries.createBeacon(
+ title, startsAt, expiresAt, lat, lon, groupID))));
+
+ if (result.data != null && result.isConcrete) {
+ final hikeJson = result.data!['createBeacon'];
+
+ final beacon = BeaconModel.fromJson(hikeJson);
+
+ // storing beacon
+ await localApi.saveBeacon(beacon);
+ return DataSuccess(beacon);
+ }
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future> joinHike(String shortcode) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Please check your internet connection!');
+ }
+ final result = await _authClient.mutate(
+ MutationOptions(document: gql(_beaconQueries.joinBeacon(shortcode))));
+
+ if (result.data != null && result.isConcrete) {
+ final hikeJosn = result.data!['joinBeacon'];
+
+ final beacon = BeaconModel.fromJson(hikeJosn);
+
+ // storing beacon
+ await localApi.saveBeacon(beacon);
+
+ return DataSuccess(beacon);
+ }
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future>> nearbyBeacons(
+ String id, String lat, String lon, double radius) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Please check your internet connection!');
+ }
+ final result = await _authClient.mutate(MutationOptions(
+ document:
+ gql(_beaconQueries.fetchNearbyBeacons(id, lat, lon, radius))));
+
+ if (result.data != null &&
+ result.isConcrete &&
+ result.data!['nearbyBeacons'] != null) {
+ List nearbyBeaconJson = result.data!['nearbyBeacons'];
+
+ List nearbyBeacons = nearbyBeaconJson
+ .map((beaconJson) => BeaconModel.fromJson(beaconJson))
+ .toList();
+
+ // storing beacons
+ for (var beacon in nearbyBeacons) {
+ await localApi.savenearbyBeacons(beacon);
+ }
+
+ return DataSuccess(nearbyBeacons);
+ }
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future>> filterBeacons(
+ String groupId, String type) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Please check your internet connection!');
+ }
+ final result = await _authClient.mutate(MutationOptions(
+ document: gql(_beaconQueries.filterBeacons(groupId, type))));
+
+ if (result.data != null &&
+ result.isConcrete &&
+ result.data!['filterBeacons'] != null) {
+ List beaconsJson = result.data!['filterBeacons'];
+
+ List beacons = beaconsJson
+ .map((beaconJson) => BeaconModel.fromJson(beaconJson))
+ .toList();
+
+ return DataSuccess(beacons);
+ } else {
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+ }
+
+ Future> deleteBeacon(String? beaconId) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Please check your internet connection!');
+ }
+ final result = await _authClient.mutate(
+ MutationOptions(document: gql(_beaconQueries.deleteBeacon(beaconId))));
+
+ if (result.data != null &&
+ result.isConcrete &&
+ result.data!['deleteBeacon'] != null) {
+ bool isDeleted = result.data!['deleteBeacon'];
+
+ return DataSuccess(isDeleted);
+ } else {
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+ }
+
+ Future> rescheduleBeacon(
+ int newExpiresAt, int newStartsAt, String beaconId) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Please check your internet connection!');
+ }
+ final result = await _authClient.mutate(MutationOptions(
+ document: gql(_beaconQueries.rescheduleHike(
+ newExpiresAt, newStartsAt, beaconId))));
+
+ if (result.data != null &&
+ result.isConcrete &&
+ result.data!['rescheduleHike'] != null) {
+ return DataSuccess(BeaconModel.fromJson(result.data!['rescheduleHike']));
+ } else {
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+ }
+
+ Future> removeMember(
+ String groupId, String memberId) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('Please check your internet connection!');
+ }
+ final result = await _authClient.mutate(MutationOptions(
+ document: gql(_groupqueries.removeMember(groupId, memberId))));
+
+ if (result.data != null &&
+ result.isConcrete &&
+ result.data!['removeMember'] != null) {
+ return DataSuccess(UserModel.fromJson(result.data!['removeMember']));
+ } else {
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+ }
+
+ String encounteredExceptionOrError(OperationException exception) {
+ if (exception.linkException != null) {
+ return 'Server not running';
+ } else {
+ return exception.graphqlErrors[0].message.toString();
+ }
+ }
+}
diff --git a/lib/data/datasource/remote/remote_hike_api.dart b/lib/data/datasource/remote/remote_hike_api.dart
new file mode 100644
index 00000000..1317f018
--- /dev/null
+++ b/lib/data/datasource/remote/remote_hike_api.dart
@@ -0,0 +1,187 @@
+import 'dart:async';
+import 'dart:developer';
+import 'package:beacon/core/queries/beacon.dart';
+import 'package:beacon/core/resources/data_state.dart';
+import 'package:beacon/data/models/beacon/beacon_model.dart';
+import 'package:beacon/data/models/landmark/landmark_model.dart';
+import 'package:beacon/data/models/location/location_model.dart';
+import 'package:beacon/data/models/subscriptions/beacon_locations_model/beacon_locations_model.dart';
+import 'package:beacon/data/models/subscriptions/join_leave_beacon_model/join_leave_beacon_model.dart';
+import 'package:beacon/data/models/user/user_model.dart';
+import 'package:beacon/domain/entities/user/user_entity.dart';
+import 'package:beacon/locator.dart';
+import 'package:google_maps_flutter/google_maps_flutter.dart';
+import 'package:graphql_flutter/graphql_flutter.dart';
+
+class RemoteHikeApi {
+ late GraphQLClient _authClient;
+ late GraphQLClient _subscriptionClient;
+
+ RemoteHikeApi(this._authClient, this._subscriptionClient);
+
+ final beaconQueries = BeaconQueries();
+
+ void loadClient(GraphQLClient authClient, GraphQLClient subscriptionClient) {
+ this._authClient = authClient;
+ this._subscriptionClient = subscriptionClient;
+ }
+
+ Future> fetchBeaconDetails(String beaconId) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+ if (!isConnected) {}
+
+ final result = await _authClient.mutate(MutationOptions(
+ document: gql(beaconQueries.fetchBeaconDetail(beaconId))));
+
+ if (result.isConcrete && result.data != null) {
+ final beaconJson = result.data!['beacon'];
+
+ final beacon = BeaconModel.fromJson(beaconJson);
+ return DataSuccess(beacon);
+ }
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future> updateBeaconLocation(
+ String? beaconId, String lat, String lon) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+ if (!isConnected) {}
+
+ final result = await _authClient.mutate(MutationOptions(
+ document: gql(beaconQueries.updateBeaconLocation(beaconId, lat, lon))));
+
+ if (result.isConcrete && result.data != null) {
+ final beaconJson = result.data!['updateBeaconLocation'];
+
+ final location = LocationModel.fromJson(beaconJson);
+ return DataSuccess(location);
+ }
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future> changeUserLocation(
+ String beaconId, LatLng latlng) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('No internet connection');
+ }
+
+ final result = await _authClient.mutate(MutationOptions(
+ document: gql(beaconQueries.changeUserLocation(beaconId,
+ latlng.latitude.toString(), latlng.longitude.toString()))));
+
+ if (result.isConcrete &&
+ result.data != null &&
+ result.data!['updateUserLocation'] != null) {
+ final user = UserModel.fromJson(result.data!['updateUserLocation']);
+ return DataSuccess(user);
+ } else {
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+ }
+
+ Future> createLandMark(
+ String id, String lat, String lon, String title) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('No internet connection');
+ }
+
+ final result = await _authClient.mutate(MutationOptions(
+ document: gql(beaconQueries.createLandmark(id, lat, lon, title))));
+
+ if (result.isConcrete &&
+ result.data != null &&
+ result.data!['createLandmark'] != null) {
+ final newLandMark =
+ LandMarkModel.fromJson(result.data!['createLandmark']);
+ return DataSuccess(newLandMark);
+ } else {
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+ }
+
+ Stream> locationUpdateSubscription(
+ String beaconId) async* {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ yield DataFailed('No internet connection');
+ }
+
+ final subscriptionOptions = SubscriptionOptions(
+ document: beaconQueries.locationUpdateGQL, variables: {'id': beaconId});
+
+ final resultStream =
+ await _subscriptionClient.subscribe(subscriptionOptions);
+
+ try {
+ await for (var stream in resultStream) {
+ if (stream.hasException) {
+ yield DataFailed('Something went wrong');
+ } else {
+ var locations =
+ BeaconLocationsModel.fromJson(stream.data!['beaconLocations']);
+ yield DataSuccess(locations);
+ }
+ }
+ } catch (e) {
+ log(e.toString());
+ }
+ }
+
+ Stream> LeaveJoinBeaconSubscription(
+ String beaconId) async* {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ yield DataFailed('No internet connection');
+ }
+
+ final subscriptionOptions = SubscriptionOptions(
+ document: beaconQueries.joinleaveBeaconSubGql,
+ variables: {'id': beaconId});
+
+ final resultStream =
+ await _subscriptionClient.subscribe(subscriptionOptions);
+
+ await for (var stream in resultStream) {
+ if (stream.hasException) {
+ yield DataFailed('Something went wrong');
+ } else {
+ var locations =
+ JoinLeaveBeaconModel.fromJson(stream.data!['JoinLeaveBeacon']);
+ yield DataSuccess(locations);
+ }
+ }
+ }
+
+ Future> sos(String id) async {
+ bool isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ return DataFailed('No internet connection');
+ }
+
+ final result = await _authClient
+ .mutate(MutationOptions(document: gql(beaconQueries.sos(id))));
+
+ if (result.isConcrete &&
+ result.data != null &&
+ result.data!['sos'] != null) {
+ return DataSuccess(UserModel.fromJson(result.data!['sos']));
+ } else {
+ return DataFailed(utils.filterException(result.exception!));
+ }
+ }
+
+ String encounteredExceptionOrError(OperationException exception) {
+ if (exception.linkException != null) {
+ return 'Server not running';
+ } else {
+ return exception.graphqlErrors[0].message.toString();
+ }
+ }
+}
diff --git a/lib/data/datasource/remote/remote_home_api.dart b/lib/data/datasource/remote/remote_home_api.dart
new file mode 100644
index 00000000..e183eced
--- /dev/null
+++ b/lib/data/datasource/remote/remote_home_api.dart
@@ -0,0 +1,207 @@
+import 'package:beacon/core/queries/group.dart';
+import 'package:beacon/core/resources/data_state.dart';
+import 'package:beacon/data/models/group/group_model.dart';
+import 'package:beacon/data/models/subscriptions/updated_group_model/updated_group_model.dart';
+import 'package:beacon/data/models/user/user_model.dart';
+import 'package:beacon/domain/entities/group/group_entity.dart';
+import 'package:beacon/locator.dart';
+import 'package:flutter/material.dart';
+import 'package:graphql_flutter/graphql_flutter.dart';
+
+class RemoteHomeApi {
+ late GraphQLClient _authClient;
+ late GraphQLClient _subscriptionClient;
+ RemoteHomeApi(this._authClient, this._subscriptionClient);
+
+ final _groupQueries = GroupQueries();
+
+ void loadClient(GraphQLClient authClient, GraphQLClient subscriptionClient) {
+ this._authClient = authClient;
+ this._subscriptionClient = subscriptionClient;
+ }
+
+ Future>> fetchUserGroups(
+ int page, int pageSize) async {
+ final isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected) {
+ // fetching the previous data stored
+ // here taking all the ids of group from the user model and then fetching the groups locally from the ids
+ // returning all groups in one go
+ UserModel? usermodel = await localApi.fetchUser();
+
+ if (usermodel != null && usermodel.groups != null) {
+ // taking user groups
+
+ int condition = (page - 1) * pageSize + pageSize;
+ int groupLen = usermodel.groups!.length;
+
+ if (condition > groupLen) {
+ condition = groupLen;
+ }
+
+ List groups = [];
+
+ for (int i = (page - 1) * pageSize; i < condition; i++) {
+ GroupModel? groupModel =
+ await localApi.getGroup(usermodel.groups![i]!.id);
+ groupModel != null ? groups.add(groupModel) : null;
+ }
+
+ return DataSuccess(groups);
+ }
+ }
+
+ final result = await _authClient.query(QueryOptions(
+ document: gql(_groupQueries.fetchUserGroups(page, pageSize))));
+
+ if (result.data != null && result.isConcrete) {
+ List groups = [];
+ List groupsData = result.data!['groups'];
+ for (var groupData in groupsData) {
+ final group = GroupModel.fromJson(groupData);
+
+ // saving locally
+ await localApi.saveGroup(group);
+
+ groups.add(group);
+ }
+ return DataSuccess(groups);
+ }
+
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future> fetchGroup(String id) async {
+ final isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected)
+ return DataFailed('Beacon is trying to connect with internet...');
+ final result = await _authClient
+ .mutate(MutationOptions(document: gql(_groupQueries.groupDetail(id))));
+
+ if (result.data != null && result.isConcrete) {
+ GroupModel group = GroupModel.fromJson(result.data!['group']);
+
+ // storing group
+ await localApi.saveGroup(group);
+
+ return DataSuccess(group);
+ }
+
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future> createGroup(String title) async {
+ final isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected)
+ return DataFailed('Beacon is trying to connect with internet...');
+ final result = await _authClient.mutate(
+ MutationOptions(document: gql(_groupQueries.createGroup(title))));
+
+ if (result.data != null && result.isConcrete) {
+ GroupModel group = GroupModel.fromJson(
+ result.data!['createGroup'] as Map);
+
+ // storing group
+ await localApi.saveGroup(group);
+
+ return DataSuccess(group);
+ }
+
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ Future> joinGroup(String shortCode) async {
+ final isConnected = await utils.checkInternetConnectivity();
+
+ if (!isConnected)
+ return DataFailed('Beacon is trying to connect with internet...');
+
+ final result = await _authClient.mutate(
+ MutationOptions(document: gql(_groupQueries.joinGroup(shortCode))));
+
+ if (result.data != null && result.isConcrete) {
+ GroupModel group = GroupModel.fromJson(
+ result.data!['joinGroup'] as Map);
+
+ // storing group
+ await localApi.saveGroup(group);
+
+ return DataSuccess(group);
+ }
+
+ return DataFailed(encounteredExceptionOrError(result.exception!));
+ }
+
+ SubscriptionOptions