Skip to content

Commit 3cd361a

Browse files
authored
Merge pull request #89 from Rezivure/staging-v1.0.2
V1.0.2+102 Update
2 parents d6c7dac + 208216f commit 3cd361a

24 files changed

+2337
-131
lines changed

android/app/src/main/AndroidManifest.xml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
99
<uses-permission android:name="android.permission.CAMERA" />
1010

11+
1112
<application
1213
android:label="Grid"
1314
android:name="${applicationName}"

lib/blocs/contacts/contacts_bloc.dart

+6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import 'package:flutter_bloc/flutter_bloc.dart';
22
import 'package:grid_frontend/repositories/location_repository.dart';
3+
import 'package:grid_frontend/repositories/sharing_preferences_repository.dart';
34
import 'package:grid_frontend/services/room_service.dart';
45
import 'package:grid_frontend/repositories/user_repository.dart';
6+
import 'package:grid_frontend/repositories/sharing_preferences_repository.dart';
57
import 'package:grid_frontend/blocs/contacts/contacts_event.dart';
68
import 'package:grid_frontend/blocs/contacts/contacts_state.dart';
79
import 'package:grid_frontend/models/contact_display.dart';
@@ -17,13 +19,16 @@ class ContactsBloc extends Bloc<ContactsEvent, ContactsState> {
1719
List<ContactDisplay> _allContacts = []; // Cache for search filtering
1820
final MapBloc mapBloc;
1921
final UserLocationProvider userLocationProvider;
22+
final SharingPreferencesRepository sharingPreferencesRepository;
2023

2124
ContactsBloc({
2225
required this.roomService,
2326
required this.userRepository,
2427
required this.mapBloc,
2528
required this.locationRepository,
2629
required this.userLocationProvider,
30+
required this.sharingPreferencesRepository,
31+
2732
}) : super(ContactsInitial()) {
2833
on<LoadContacts>(_onLoadContacts);
2934
on<RefreshContacts>(_onRefreshContacts);
@@ -66,6 +71,7 @@ class ContactsBloc extends Bloc<ContactsEvent, ContactsState> {
6671
userLocationProvider.removeUserLocation(event.userId);
6772
mapBloc.add(RemoveUserLocation(event.userId));
6873
}
74+
await sharingPreferencesRepository.deleteSharingPreferences(event.userId, 'user');
6975
_allContacts = await _loadContacts();
7076
emit(ContactsLoaded(_allContacts));
7177
}

lib/main.dart

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_dotenv/flutter_dotenv.dart';
33
import 'package:flutter_bloc/flutter_bloc.dart';
4+
import 'package:grid_frontend/services/android_background_task.dart';
45
import 'package:path_provider/path_provider.dart';
56
import 'package:provider/provider.dart';
67
import 'package:shared_preferences/shared_preferences.dart';
@@ -36,10 +37,16 @@ import 'package:grid_frontend/blocs/contacts/contacts_bloc.dart';
3637
import 'package:grid_frontend/blocs/groups/groups_bloc.dart';
3738

3839
import 'package:grid_frontend/widgets/version_wrapper.dart';
40+
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg;
41+
42+
43+
3944

4045
void main() async {
4146
WidgetsFlutterBinding.ensureInitialized();
4247

48+
bg.BackgroundGeolocation.registerHeadlessTask(headlessTask);
49+
4350
// Load .env file
4451
await dotenv.load(fileName: ".env");
4552

@@ -60,6 +67,7 @@ void main() async {
6067
await client.init();
6168

6269
// Attempt to restore session
70+
// TODO: this code chunk may do nothing actually
6371
final prefs = await SharedPreferences.getInstance();
6472
String? token = prefs.getString('token');
6573

@@ -72,6 +80,7 @@ void main() async {
7280
}
7381
}
7482

83+
7584
// Initialize repositories
7685
final userRepository = UserRepository(databaseService);
7786
final roomRepository = RoomRepository(databaseService);
@@ -80,7 +89,7 @@ void main() async {
8089
final userKeysRepository = UserKeysRepository(databaseService);
8190
final locationManager = LocationManager();
8291
// Initialize services
83-
final userService = UserService(client, locationRepository);
92+
final userService = UserService(client, locationRepository, sharingPreferencesRepository);
8493
final roomService = RoomService(client, userService, userRepository, userKeysRepository, roomRepository, locationRepository, sharingPreferencesRepository, locationManager);
8594

8695
final messageParser = MessageParser();
@@ -145,6 +154,7 @@ void main() async {
145154
mapBloc: context.read<MapBloc>(),
146155
locationRepository: context.read<LocationRepository>(),
147156
userLocationProvider: context.read<UserLocationProvider>(),
157+
sharingPreferencesRepository: context.read<SharingPreferencesRepository>(),
148158
),
149159
),
150160
BlocProvider<GroupsBloc>(
@@ -169,6 +179,7 @@ void main() async {
169179
locationRepository,
170180
context.read<GroupsBloc>(),
171181
context.read<UserLocationProvider>(),
182+
context.read<SharingPreferencesRepository>(),
172183
)..startSync(),
173184
update: (context, mapBloc, contactsBloc, groupsBloc, previous) =>
174185
previous ?? SyncManager(
@@ -182,6 +193,7 @@ void main() async {
182193
locationRepository,
183194
groupsBloc,
184195
context.read<UserLocationProvider>(),
196+
sharingPreferencesRepository,
185197
)..startSync(),
186198
),
187199
],

lib/models/sharing_preferences.dart

+23-12
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import 'dart:convert';
22

3+
import 'package:grid_frontend/models/sharing_window.dart';
4+
35
class SharingPreferences {
46
final int? id;
5-
final String targetId; // ID of the user or group
6-
final String targetType; // Type: 'user' or 'group'
7-
final bool activeSharing; // Whether sharing is currently active
8-
final Map<String, dynamic>? sharePeriods; // Custom sharing periods (optional)
7+
final String targetId;
8+
final String targetType;
9+
final bool activeSharing;
10+
final List<SharingWindow>? shareWindows;
911

1012
SharingPreferences({
1113
this.id,
1214
required this.targetId,
1315
required this.targetType,
1416
required this.activeSharing,
15-
this.sharePeriods,
17+
this.shareWindows,
1618
});
1719

1820
// Convert model to a map for database insertion
@@ -21,21 +23,30 @@ class SharingPreferences {
2123
'id': id,
2224
'targetId': targetId,
2325
'targetType': targetType,
24-
'activeSharing': activeSharing ? 1 : 0, // Convert bool to integer
25-
'sharePeriods': sharePeriods != null ? jsonEncode(sharePeriods) : null, // Encode as JSON
26+
'activeSharing': activeSharing ? 1 : 0,
27+
// Encode the list of windows as JSON (or null if no windows)
28+
'sharePeriods': shareWindows != null
29+
? jsonEncode(shareWindows!.map((w) => w.toJson()).toList())
30+
: null,
2631
};
2732
}
2833

29-
// Create an instance from a database map
34+
3035
factory SharingPreferences.fromMap(Map<String, dynamic> map) {
36+
// If 'sharePeriods' is not null, decode it and parse each window
37+
final rawJson = map['sharePeriods'] as String?;
38+
List<SharingWindow>? windows;
39+
if (rawJson != null && rawJson.isNotEmpty) {
40+
final List decoded = jsonDecode(rawJson);
41+
windows = decoded.map((item) => SharingWindow.fromJson(item)).toList().cast<SharingWindow>();
42+
}
43+
3144
return SharingPreferences(
3245
id: map['id'] as int?,
3346
targetId: map['targetId'] as String,
3447
targetType: map['targetType'] as String,
35-
activeSharing: (map['activeSharing'] as int) == 1, // Convert integer to bool
36-
sharePeriods: map['sharePeriods'] != null
37-
? jsonDecode(map['sharePeriods'] as String) as Map<String, dynamic>
38-
: null, // Decode JSON if not null
48+
activeSharing: (map['activeSharing'] as int) == 1,
49+
shareWindows: windows,
3950
);
4051
}
4152
}

lib/models/sharing_window.dart

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
class SharingWindow {
2+
final String label;
3+
final List<int> days; // e.g. 0 for Mon, 1 for Tue, ...
4+
final bool isAllDay;
5+
final String? startTime; // "09:00"
6+
final String? endTime; // "17:00"
7+
final bool isActive; // <--- new field
8+
9+
SharingWindow({
10+
required this.label,
11+
required this.days,
12+
required this.isAllDay,
13+
required this.isActive,
14+
this.startTime,
15+
this.endTime,
16+
});
17+
18+
Map<String, dynamic> toJson() => {
19+
'label': label,
20+
'days': days,
21+
'isAllDay': isAllDay,
22+
'startTime': startTime,
23+
'endTime': endTime,
24+
'isActive': isActive,
25+
};
26+
27+
factory SharingWindow.fromJson(Map<String, dynamic> json) => SharingWindow(
28+
label: json['label'] as String,
29+
days: (json['days'] as List<dynamic>).map((e) => e as int).toList(),
30+
isAllDay: json['isAllDay'] as bool,
31+
startTime: json['startTime'] as String?,
32+
endTime: json['endTime'] as String?,
33+
isActive: json['isActive'] == null
34+
? true
35+
: json['isActive'] as bool,
36+
);
37+
}

lib/providers/auth_provider.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class AuthProvider with ChangeNotifier {
3838

3939
final prefs = await SharedPreferences.getInstance();
4040
//await prefs.setBool('isLoggedIn', _isLoggedIn);
41-
//await prefs.setString('token', jwt);
41+
await prefs.setString('loginToken', jwt);
4242

4343
try {
4444
// Check if we can communicate with the Matrix server

lib/screens/map/map_tab.dart

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_map/flutter_map.dart';
33
import 'package:flutter_bloc/flutter_bloc.dart';
4+
import 'package:grid_frontend/repositories/sharing_preferences_repository.dart';
5+
import 'package:grid_frontend/repositories/user_repository.dart';
46
import 'package:grid_frontend/services/sync_manager.dart';
57
import 'package:latlong2/latlong.dart';
68
import 'package:vector_map_tiles/vector_map_tiles.dart';
@@ -21,6 +23,8 @@ import 'package:grid_frontend/services/room_service.dart';
2123
import 'package:grid_frontend/services/user_service.dart';
2224
import 'package:grid_frontend/services/location_manager.dart';
2325

26+
import '../../services/backwards_compatibility_service.dart';
27+
2428

2529
class MapTab extends StatefulWidget {
2630
final LatLng? friendLocation;
@@ -36,6 +40,8 @@ class _MapTabState extends State<MapTab> with TickerProviderStateMixin, WidgetsB
3640
late final RoomService _roomService;
3741
late final UserService _userService;
3842
late final SyncManager _syncManager;
43+
late final UserRepository userRepository;
44+
late final SharingPreferencesRepository sharingPreferencesRepository;
3945

4046
bool _isMapReady = false;
4147
bool _followUser = true;
@@ -65,6 +71,8 @@ class _MapTabState extends State<MapTab> with TickerProviderStateMixin, WidgetsB
6571
_userService = context.read<UserService>();
6672
_locationManager = context.read<LocationManager>();
6773
_syncManager = context.read<SyncManager>();
74+
userRepository = context.read<UserRepository>();
75+
sharingPreferencesRepository = context.read<SharingPreferencesRepository>();
6876

6977
_syncManager.initialize();
7078

@@ -91,6 +99,15 @@ class _MapTabState extends State<MapTab> with TickerProviderStateMixin, WidgetsB
9199
_syncManager.handleAppLifecycleState(state == AppLifecycleState.resumed);
92100
}
93101

102+
void _backwardsCompatibilityUpdate() async {
103+
final backwardsService = BackwardsCompatibilityService(
104+
userRepository,
105+
sharingPreferencesRepository,
106+
);
107+
108+
await backwardsService.runBackfillIfNeeded();
109+
}
110+
94111
Future<void> _loadMapProvider() async {
95112
try {
96113
final prefs = await SharedPreferences.getInstance();
@@ -182,7 +199,7 @@ class _MapTabState extends State<MapTab> with TickerProviderStateMixin, WidgetsB
182199
theme: _mapTheme,
183200
tileProviders: TileProviders({'protomaps': _tileProvider!}),
184201
fileCacheTtl: const Duration(hours: 24),
185-
concurrency: 20,
202+
concurrency: 10,
186203
),
187204
CurrentLocationLayer(
188205
alignPositionOnUpdate: _followUser ? AlignOnUpdate.always : AlignOnUpdate.never,

lib/screens/onboarding/splash_screen.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ class _SplashScreenState extends State<SplashScreen> {
2525
await Future.delayed(Duration(seconds: 2));
2626

2727
// Load the token from SharedPreferences
28+
// TODO: delete code perhaps, doesn't seem to do anything or impact
2829
String? token = await _loadFromPrefs();
29-
print(token);
3030

3131
final client = Provider.of<Client>(context, listen: false);
3232

0 commit comments

Comments
 (0)