kopia lustrzana https://gitlab.com/mysocialportal/relatica
				
				
				
			Add ActiveProfileSelector to all appropriate managers/services/repos/etc
							rodzic
							
								
									b0ee7fabac
								
							
						
					
					
						commit
						112910d2b8
					
				| 
						 | 
				
			
			@ -7,6 +7,7 @@ import '../../models/gallery_data.dart';
 | 
			
		|||
import '../../models/media_attachment_uploads/new_entry_media_items.dart';
 | 
			
		||||
import '../../services/gallery_service.dart';
 | 
			
		||||
import '../../services/media_upload_attachment_helper.dart';
 | 
			
		||||
import '../../utils/active_profile_selector.dart';
 | 
			
		||||
import '../../utils/snackbar_builder.dart';
 | 
			
		||||
import '../padding.dart';
 | 
			
		||||
import 'media_upload_editor_control.dart';
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +30,10 @@ class _MediaUploadsControlState extends State<MediaUploadsControl> {
 | 
			
		|||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    _logger.finest('Building');
 | 
			
		||||
    final galleryManager = context.watch<GalleryService>();
 | 
			
		||||
    final galleryManager = context
 | 
			
		||||
        .watch<ActiveProfileSelector<GalleryService>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final galleries = galleryManager.getGalleries();
 | 
			
		||||
    return Column(
 | 
			
		||||
      children: [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,6 @@ import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart
 | 
			
		|||
import 'package:go_router/go_router.dart';
 | 
			
		||||
import 'package:logging/logging.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
import 'package:relatica/utils/active_profile_selector.dart';
 | 
			
		||||
 | 
			
		||||
import '../globals.dart';
 | 
			
		||||
import '../models/user_notification.dart';
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +10,7 @@ import '../routes.dart';
 | 
			
		|||
import '../services/connections_manager.dart';
 | 
			
		||||
import '../services/notifications_manager.dart';
 | 
			
		||||
import '../services/timeline_manager.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
import '../utils/dateutils.dart';
 | 
			
		||||
import '../utils/snackbar_builder.dart';
 | 
			
		||||
import 'image_control.dart';
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,8 @@ class NotificationControl extends StatelessWidget {
 | 
			
		|||
  });
 | 
			
		||||
 | 
			
		||||
  Future<void> _goToStatus(BuildContext context) async {
 | 
			
		||||
    final manager = getIt<TimelineManager>();
 | 
			
		||||
    final manager =
 | 
			
		||||
        getIt<ActiveProfileSelector<TimelineManager>>().activeEntry.value;
 | 
			
		||||
    final existingPostData = manager.getPostTreeEntryBy(notification.iid);
 | 
			
		||||
    if (existingPostData.isSuccess) {
 | 
			
		||||
      context
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,13 +58,14 @@ class StandardAppDrawer extends StatelessWidget {
 | 
			
		|||
            'Settings',
 | 
			
		||||
            () => context.pushNamed(ScreenPaths.settings),
 | 
			
		||||
          ),
 | 
			
		||||
          buildMenuButton(context, 'Clear Caches', () async {
 | 
			
		||||
            final confirm = await showYesNoDialog(
 | 
			
		||||
                context, 'You want to clear all memory and disk cache data?');
 | 
			
		||||
            if (confirm == true) {
 | 
			
		||||
              clearCaches();
 | 
			
		||||
            }
 | 
			
		||||
          }),
 | 
			
		||||
          // TODO Add back in clearing ability but has to do disk caches too
 | 
			
		||||
          // buildMenuButton(context, 'Clear Caches', () async {
 | 
			
		||||
          //   final confirm = await showYesNoDialog(
 | 
			
		||||
          //       context, 'You want to clear all memory and disk cache data?');
 | 
			
		||||
          //   if (confirm == true) {
 | 
			
		||||
          //     clearCaches();
 | 
			
		||||
          //   }
 | 
			
		||||
          // }),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import 'package:logging/logging.dart';
 | 
			
		|||
import '../../globals.dart';
 | 
			
		||||
import '../../models/timeline_entry.dart';
 | 
			
		||||
import '../../services/timeline_manager.dart';
 | 
			
		||||
import '../../utils/active_profile_selector.dart';
 | 
			
		||||
import '../../utils/clipboard_utils.dart';
 | 
			
		||||
import '../../utils/snackbar_builder.dart';
 | 
			
		||||
import '../../utils/url_opening_utils.dart';
 | 
			
		||||
| 
						 | 
				
			
			@ -50,8 +51,10 @@ class _InteractionsBarControlState extends State<InteractionsBarControl> {
 | 
			
		|||
    });
 | 
			
		||||
    final newState = !isFavorited;
 | 
			
		||||
    _logger.finest('Trying to toggle favorite from $isFavorited to $newState');
 | 
			
		||||
    final result = await getIt<TimelineManager>()
 | 
			
		||||
        .toggleFavorited(widget.entry.id, newState);
 | 
			
		||||
    final result = await getIt<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .andThenAsync(
 | 
			
		||||
            (tm) async => await tm.toggleFavorited(widget.entry.id, newState));
 | 
			
		||||
    result.match(onSuccess: (update) {
 | 
			
		||||
      setState(() {
 | 
			
		||||
        _logger.finest(
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +74,10 @@ class _InteractionsBarControlState extends State<InteractionsBarControl> {
 | 
			
		|||
    });
 | 
			
		||||
    final id = widget.entry.id;
 | 
			
		||||
    _logger.finest('Trying to reshare $id');
 | 
			
		||||
    final result = await getIt<TimelineManager>().resharePost(id);
 | 
			
		||||
    final result = await getIt<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .andThenAsync((tm) async => await tm.resharePost(id));
 | 
			
		||||
 | 
			
		||||
    result.match(onSuccess: (update) {
 | 
			
		||||
      setState(() {
 | 
			
		||||
        _logger.finest('Success resharing post by ${widget.entry.author}');
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +101,10 @@ class _InteractionsBarControlState extends State<InteractionsBarControl> {
 | 
			
		|||
    final confirm =
 | 
			
		||||
        await showYesNoDialog(context, 'Delete ${isPost ? "Post" : "Comment"}');
 | 
			
		||||
    if (confirm == true) {
 | 
			
		||||
      await getIt<TimelineManager>().deleteEntryById(widget.entry.id);
 | 
			
		||||
      await getIt<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
          .activeEntry
 | 
			
		||||
          .andThenAsync(
 | 
			
		||||
              (tm) async => await tm.deleteEntryById(widget.entry.id));
 | 
			
		||||
    }
 | 
			
		||||
    setState(() {
 | 
			
		||||
      isProcessing = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +117,9 @@ class _InteractionsBarControlState extends State<InteractionsBarControl> {
 | 
			
		|||
    });
 | 
			
		||||
    final id = widget.entry.id;
 | 
			
		||||
    _logger.finest('Trying to un-reshare $id');
 | 
			
		||||
    final result = await getIt<TimelineManager>().unResharePost(id);
 | 
			
		||||
    final result = await getIt<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .andThenAsync((tm) async => await tm.unResharePost(id));
 | 
			
		||||
    result.match(onSuccess: (update) {
 | 
			
		||||
      setState(() {
 | 
			
		||||
        _logger.finest('Success un-resharing post by ${widget.entry.author}');
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import '../../models/entry_tree_item.dart';
 | 
			
		|||
import '../../models/flattened_tree_item.dart';
 | 
			
		||||
import '../../models/timeline_entry.dart';
 | 
			
		||||
import '../../services/timeline_manager.dart';
 | 
			
		||||
import '../../utils/active_profile_selector.dart';
 | 
			
		||||
import '../../utils/entry_tree_item_flattening.dart';
 | 
			
		||||
import 'flattened_tree_entry_control.dart';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +58,10 @@ class _PostControlState extends State<PostControl> {
 | 
			
		|||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final manager = context.watch<TimelineManager>();
 | 
			
		||||
    final manager = context
 | 
			
		||||
        .watch<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    _logger.finest('Building ${item.entry.toShortString()}');
 | 
			
		||||
    final items = widget.originalItem.flatten(topLevelOnly: !showComments);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
 | 
			
		|||
 | 
			
		||||
import '../../models/TimelineIdentifiers.dart';
 | 
			
		||||
import '../../services/timeline_manager.dart';
 | 
			
		||||
import '../../utils/active_profile_selector.dart';
 | 
			
		||||
import 'post_control.dart';
 | 
			
		||||
 | 
			
		||||
class TimelinePanel extends StatelessWidget {
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +15,10 @@ class TimelinePanel extends StatelessWidget {
 | 
			
		|||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final manager = context.watch<TimelineManager>();
 | 
			
		||||
    final manager = context
 | 
			
		||||
        .watch<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final result = manager.getTimeline(timeline);
 | 
			
		||||
    if (result.isFailure) {
 | 
			
		||||
      return Center(child: Text('Error getting timeline: ${result.error}'));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ class IGroupsRepo {
 | 
			
		|||
    throw UnimplementedError();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void clearGroups() {
 | 
			
		||||
  void clearMyGroups() {
 | 
			
		||||
    throw UnimplementedError();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ class MemoryGroupsRepo implements IGroupsRepo {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void clearGroups() {
 | 
			
		||||
  void clearMyGroups() {
 | 
			
		||||
    _myGroups.clear();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,4 @@
 | 
			
		|||
import 'package:logging/logging.dart';
 | 
			
		||||
import 'package:relatica/utils/active_profile_selector.dart';
 | 
			
		||||
 | 
			
		||||
import 'data/interfaces/connections_repo_intf.dart';
 | 
			
		||||
import 'data/interfaces/groups_repo.intf.dart';
 | 
			
		||||
| 
						 | 
				
			
			@ -23,36 +22,34 @@ import 'services/notifications_manager.dart';
 | 
			
		|||
import 'services/secrets_service.dart';
 | 
			
		||||
import 'services/setting_service.dart';
 | 
			
		||||
import 'services/timeline_manager.dart';
 | 
			
		||||
import 'utils/active_profile_selector.dart';
 | 
			
		||||
 | 
			
		||||
final _logger = Logger('DI_Init');
 | 
			
		||||
 | 
			
		||||
Future<void> dependencyInjectionInitialization() async {
 | 
			
		||||
  final entryManagerService = EntryManagerService();
 | 
			
		||||
  final timelineManager = TimelineManager();
 | 
			
		||||
  final galleryService = GalleryService();
 | 
			
		||||
  final objectBoxCache = await ObjectBoxCache.create();
 | 
			
		||||
  getIt.registerSingleton<ObjectBoxCache>(objectBoxCache);
 | 
			
		||||
  getIt.registerSingleton<IHashtagRepo>(ObjectBoxHashtagRepo());
 | 
			
		||||
  getIt.registerSingleton<HashtagService>(HashtagService());
 | 
			
		||||
  getIt.registerSingleton<NetworkStatusService>(NetworkStatusService());
 | 
			
		||||
 | 
			
		||||
  final settingsService = SettingsService();
 | 
			
		||||
  await settingsService.initialize();
 | 
			
		||||
  getIt.registerSingleton<SettingsService>(settingsService);
 | 
			
		||||
  getIt.registerLazySingleton<NetworkStatusService>(
 | 
			
		||||
      () => NetworkStatusService());
 | 
			
		||||
 | 
			
		||||
  getIt.registerSingleton<ActiveProfileSelector<IConnectionsRepo>>(
 | 
			
		||||
      ActiveProfileSelector(null));
 | 
			
		||||
 | 
			
		||||
  final secretsService = SecretsService();
 | 
			
		||||
  final serviceInit = await secretsService.initialize();
 | 
			
		||||
 | 
			
		||||
  final authService = AccountsService(secretsService);
 | 
			
		||||
  if (serviceInit.isFailure) {
 | 
			
		||||
    _logger.severe('Error initializing credentials');
 | 
			
		||||
  } else {
 | 
			
		||||
    await authService.initialize();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  final objectBoxCache = await ObjectBoxCache.create();
 | 
			
		||||
  getIt.registerSingleton<ObjectBoxCache>(objectBoxCache);
 | 
			
		||||
 | 
			
		||||
  getIt.registerSingleton<IHashtagRepo>(ObjectBoxHashtagRepo());
 | 
			
		||||
  getIt.registerSingleton<AccountsService>(authService);
 | 
			
		||||
 | 
			
		||||
  getIt.registerSingleton<ActiveProfileSelector<IGroupsRepo>>(
 | 
			
		||||
      ActiveProfileSelector((p) => MemoryGroupsRepo()));
 | 
			
		||||
| 
						 | 
				
			
			@ -65,24 +62,26 @@ Future<void> dependencyInjectionInitialization() async {
 | 
			
		|||
    ),
 | 
			
		||||
  ));
 | 
			
		||||
 | 
			
		||||
  getIt.registerLazySingleton<HashtagService>(() => HashtagService());
 | 
			
		||||
  //TODO wrap it ActiveProfileSelector
 | 
			
		||||
  getIt.registerSingleton(galleryService);
 | 
			
		||||
  //TODO wrap it ActiveProfileSelector
 | 
			
		||||
  getIt.registerSingleton<EntryManagerService>(entryManagerService);
 | 
			
		||||
  getIt.registerSingleton<AccountsService>(authService);
 | 
			
		||||
  //TODO wrap it ActiveProfileSelector
 | 
			
		||||
  getIt.registerSingleton<TimelineManager>(timelineManager);
 | 
			
		||||
  getIt.registerSingleton<ActiveProfileSelector<GalleryService>>(
 | 
			
		||||
      ActiveProfileSelector((p) => GalleryService()));
 | 
			
		||||
  getIt.registerSingleton<ActiveProfileSelector<EntryManagerService>>(
 | 
			
		||||
      ActiveProfileSelector((p) => EntryManagerService()));
 | 
			
		||||
  getIt.registerSingleton<ActiveProfileSelector<TimelineManager>>(
 | 
			
		||||
      ActiveProfileSelector((p) => TimelineManager(
 | 
			
		||||
            getIt<ActiveProfileSelector<IGroupsRepo>>().getForProfile(p).value,
 | 
			
		||||
            getIt<ActiveProfileSelector<EntryManagerService>>()
 | 
			
		||||
                .getForProfile(p)
 | 
			
		||||
                .value,
 | 
			
		||||
          )));
 | 
			
		||||
  getIt.registerSingleton<ActiveProfileSelector<NotificationsManager>>(
 | 
			
		||||
      ActiveProfileSelector((_) => NotificationsManager()));
 | 
			
		||||
  getIt.registerSingleton<ActiveProfileSelector<DirectMessageService>>(
 | 
			
		||||
      ActiveProfileSelector((p) => DirectMessageService()));
 | 
			
		||||
  getIt.registerSingleton<ActiveProfileSelector<InteractionsManager>>(
 | 
			
		||||
      ActiveProfileSelector((p) => InteractionsManager()));
 | 
			
		||||
 | 
			
		||||
  getIt.registerLazySingleton<MediaUploadAttachmentHelper>(
 | 
			
		||||
      () => MediaUploadAttachmentHelper());
 | 
			
		||||
  getIt.registerLazySingleton<ActiveProfileSelector<NotificationsManager>>(
 | 
			
		||||
      () => ActiveProfileSelector((_) => NotificationsManager()));
 | 
			
		||||
  //TODO wrap it ActiveProfileSelector
 | 
			
		||||
  getIt.registerLazySingleton<DirectMessageService>(
 | 
			
		||||
      () => DirectMessageService());
 | 
			
		||||
 | 
			
		||||
  //TODO wrap it ActiveProfileSelector
 | 
			
		||||
  getIt.registerLazySingleton<InteractionsManager>(() => InteractionsManager());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Future<void> updateProfileDependencyInjectors(Profile profile) async {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,10 +5,6 @@ import 'package:flutter/material.dart';
 | 
			
		|||
import 'package:get_it/get_it.dart';
 | 
			
		||||
import 'package:uuid/uuid.dart';
 | 
			
		||||
 | 
			
		||||
import 'data/interfaces/connections_repo_intf.dart';
 | 
			
		||||
import 'services/notifications_manager.dart';
 | 
			
		||||
import 'services/timeline_manager.dart';
 | 
			
		||||
 | 
			
		||||
final getIt = GetIt.instance;
 | 
			
		||||
 | 
			
		||||
String randomId() => const Uuid().v4().toString();
 | 
			
		||||
| 
						 | 
				
			
			@ -88,8 +84,8 @@ Future<String?> showChooseOptions(
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clearCaches() {
 | 
			
		||||
  getIt<TimelineManager>().clear();
 | 
			
		||||
  getIt<IConnectionsRepo>().clear();
 | 
			
		||||
  getIt<NotificationsManager>().clear();
 | 
			
		||||
}
 | 
			
		||||
// void clearCaches() {
 | 
			
		||||
//   getIt<TimelineManager>().clear();
 | 
			
		||||
//   getIt<IConnectionsRepo>().clear();
 | 
			
		||||
//   getIt<NotificationsManager>().clear();
 | 
			
		||||
// }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,31 +62,37 @@ class App extends StatelessWidget {
 | 
			
		|||
                    getIt<ActiveProfileSelector<ConnectionsManager>>(),
 | 
			
		||||
                lazy: true,
 | 
			
		||||
              ),
 | 
			
		||||
              ChangeNotifierProvider<EntryManagerService>(
 | 
			
		||||
                create: (_) => getIt<EntryManagerService>(),
 | 
			
		||||
              ChangeNotifierProvider<
 | 
			
		||||
                  ActiveProfileSelector<EntryManagerService>>(
 | 
			
		||||
                create: (_) =>
 | 
			
		||||
                    getIt<ActiveProfileSelector<EntryManagerService>>(),
 | 
			
		||||
                lazy: true,
 | 
			
		||||
              ),
 | 
			
		||||
              ChangeNotifierProvider<GalleryService>(
 | 
			
		||||
                create: (_) => getIt<GalleryService>(),
 | 
			
		||||
              ChangeNotifierProvider<ActiveProfileSelector<GalleryService>>(
 | 
			
		||||
                create: (_) => getIt<ActiveProfileSelector<GalleryService>>(),
 | 
			
		||||
                lazy: true,
 | 
			
		||||
              ),
 | 
			
		||||
              ChangeNotifierProvider<HashtagService>(
 | 
			
		||||
                create: (_) => getIt<HashtagService>(),
 | 
			
		||||
                lazy: true,
 | 
			
		||||
              ),
 | 
			
		||||
              ChangeNotifierProvider<TimelineManager>(
 | 
			
		||||
                create: (_) => getIt<TimelineManager>(),
 | 
			
		||||
              ChangeNotifierProvider<ActiveProfileSelector<TimelineManager>>(
 | 
			
		||||
                create: (_) => getIt<ActiveProfileSelector<TimelineManager>>(),
 | 
			
		||||
              ),
 | 
			
		||||
              ChangeNotifierProvider<
 | 
			
		||||
                  ActiveProfileSelector<NotificationsManager>>(
 | 
			
		||||
                create: (_) =>
 | 
			
		||||
                    getIt<ActiveProfileSelector<NotificationsManager>>(),
 | 
			
		||||
              ),
 | 
			
		||||
              ChangeNotifierProvider<DirectMessageService>(
 | 
			
		||||
                create: (_) => getIt<DirectMessageService>(),
 | 
			
		||||
              ChangeNotifierProvider<
 | 
			
		||||
                  ActiveProfileSelector<DirectMessageService>>(
 | 
			
		||||
                create: (_) =>
 | 
			
		||||
                    getIt<ActiveProfileSelector<DirectMessageService>>(),
 | 
			
		||||
              ),
 | 
			
		||||
              ChangeNotifierProvider<InteractionsManager>(
 | 
			
		||||
                create: (_) => getIt<InteractionsManager>(),
 | 
			
		||||
              ChangeNotifierProvider<
 | 
			
		||||
                  ActiveProfileSelector<InteractionsManager>>(
 | 
			
		||||
                create: (_) =>
 | 
			
		||||
                    getIt<ActiveProfileSelector<InteractionsManager>>(),
 | 
			
		||||
              )
 | 
			
		||||
            ],
 | 
			
		||||
            child: MaterialApp.router(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,16 @@
 | 
			
		|||
class GroupData {
 | 
			
		||||
  final String id;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  bool operator ==(Object other) =>
 | 
			
		||||
      identical(this, other) ||
 | 
			
		||||
      other is GroupData &&
 | 
			
		||||
          runtimeType == other.runtimeType &&
 | 
			
		||||
          id == other.id &&
 | 
			
		||||
          name == other.name;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  int get hashCode => id.hashCode ^ name.hashCode;
 | 
			
		||||
  final String name;
 | 
			
		||||
 | 
			
		||||
  GroupData(this.id, this.name);
 | 
			
		||||
| 
						 | 
				
			
			@ -8,12 +19,4 @@ class GroupData {
 | 
			
		|||
  String toString() {
 | 
			
		||||
    return 'GroupData{id: $id, name: $name}';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  bool operator ==(Object other) =>
 | 
			
		||||
      identical(this, other) ||
 | 
			
		||||
      other is GroupData && runtimeType == other.runtimeType && id == other.id;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  int get hashCode => id.hashCode;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,11 +11,13 @@ import '../controls/autocomplete/mention_autocomplete_options.dart';
 | 
			
		|||
import '../controls/entry_media_attachments/gallery_selector_control.dart';
 | 
			
		||||
import '../controls/entry_media_attachments/media_uploads_control.dart';
 | 
			
		||||
import '../controls/padding.dart';
 | 
			
		||||
import '../controls/standard_appbar.dart';
 | 
			
		||||
import '../controls/timeline/status_header_control.dart';
 | 
			
		||||
import '../models/image_entry.dart';
 | 
			
		||||
import '../models/media_attachment_uploads/new_entry_media_items.dart';
 | 
			
		||||
import '../models/timeline_entry.dart';
 | 
			
		||||
import '../services/timeline_manager.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
import '../utils/snackbar_builder.dart';
 | 
			
		||||
 | 
			
		||||
class EditorScreen extends StatefulWidget {
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +55,10 @@ class _EditorScreenState extends State<EditorScreen> {
 | 
			
		|||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    final manager = context.read<TimelineManager>();
 | 
			
		||||
    final manager = context
 | 
			
		||||
        .read<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    manager.getEntryById(widget.parentId).match(onSuccess: (entry) {
 | 
			
		||||
      spoilerController.text = entry.spoilerText;
 | 
			
		||||
      parentEntry = entry;
 | 
			
		||||
| 
						 | 
				
			
			@ -97,7 +102,10 @@ class _EditorScreenState extends State<EditorScreen> {
 | 
			
		|||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    _logger.finest('Build editor $isComment $parentEntry');
 | 
			
		||||
    final manager = context.read<TimelineManager>();
 | 
			
		||||
    final manager = context
 | 
			
		||||
        .read<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
 | 
			
		||||
    final mainBody = Padding(
 | 
			
		||||
      padding: const EdgeInsets.all(8.0),
 | 
			
		||||
| 
						 | 
				
			
			@ -162,10 +170,9 @@ class _EditorScreenState extends State<EditorScreen> {
 | 
			
		|||
    );
 | 
			
		||||
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: AppBar(
 | 
			
		||||
        automaticallyImplyLeading: false,
 | 
			
		||||
        title: Text(widget.id.isEmpty ? 'New $statusType' : 'Edit $statusType'),
 | 
			
		||||
      ),
 | 
			
		||||
      appBar: StandardAppBar.build(
 | 
			
		||||
          context, widget.id.isEmpty ? 'New $statusType' : 'Edit $statusType',
 | 
			
		||||
          withDrawer: true),
 | 
			
		||||
      body: isSubmitting ? submittingBody : mainBody,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ import '../models/gallery_data.dart';
 | 
			
		|||
import '../models/image_entry.dart';
 | 
			
		||||
import '../serializers/friendica/image_entry_friendica_extensions.dart';
 | 
			
		||||
import '../services/gallery_service.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
import 'image_viewer_screen.dart';
 | 
			
		||||
 | 
			
		||||
class ExistingImageSelectorScreen extends StatefulWidget {
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +22,10 @@ class _ExistingImageSelectorScreenState
 | 
			
		|||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final service = context.watch<GalleryService>();
 | 
			
		||||
    final service = context
 | 
			
		||||
        .watch<ActiveProfileSelector<GalleryService>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final title = selectedImages.isEmpty
 | 
			
		||||
        ? 'Select Image(s)'
 | 
			
		||||
        : '${selectedImages.length} selected';
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import '../controls/status_and_refresh_button.dart';
 | 
			
		|||
import '../globals.dart';
 | 
			
		||||
import '../services/gallery_service.dart';
 | 
			
		||||
import '../services/network_status_service.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
 | 
			
		||||
class GalleryBrowsersScreen extends StatelessWidget {
 | 
			
		||||
  static final _logger = Logger('$GalleryBrowsersScreen');
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +17,10 @@ class GalleryBrowsersScreen extends StatelessWidget {
 | 
			
		|||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    _logger.finest('Building');
 | 
			
		||||
    final service = context.watch<GalleryService>();
 | 
			
		||||
    final service = context
 | 
			
		||||
        .watch<ActiveProfileSelector<GalleryService>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final nss = getIt<NetworkStatusService>();
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: StandardAppBar.build(context, 'Galleries', actions: [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import '../globals.dart';
 | 
			
		|||
import '../serializers/friendica/image_entry_friendica_extensions.dart';
 | 
			
		||||
import '../services/gallery_service.dart';
 | 
			
		||||
import '../services/network_status_service.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
import 'image_viewer_screen.dart';
 | 
			
		||||
 | 
			
		||||
class GalleryScreen extends StatelessWidget {
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +23,10 @@ class GalleryScreen extends StatelessWidget {
 | 
			
		|||
  Widget build(BuildContext context) {
 | 
			
		||||
    _logger.finest('Building');
 | 
			
		||||
    final nss = getIt<NetworkStatusService>();
 | 
			
		||||
    final service = context.watch<GalleryService>();
 | 
			
		||||
    final service = context
 | 
			
		||||
        .watch<ActiveProfileSelector<GalleryService>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final body = service.getGallery(galleryName).fold(
 | 
			
		||||
          onSuccess: (galleryData) =>
 | 
			
		||||
              buildBody(context, service, galleryData.count),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,18 +3,19 @@ import 'package:flutter/material.dart';
 | 
			
		|||
import 'package:go_router/go_router.dart';
 | 
			
		||||
import 'package:logging/logging.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
import 'package:relatica/controls/standard_app_drawer.dart';
 | 
			
		||||
import 'package:relatica/services/auth_service.dart';
 | 
			
		||||
 | 
			
		||||
import '../controls/app_bottom_nav_bar.dart';
 | 
			
		||||
import '../controls/padding.dart';
 | 
			
		||||
import '../controls/standard_app_drawer.dart';
 | 
			
		||||
import '../controls/status_and_refresh_button.dart';
 | 
			
		||||
import '../controls/timeline/timeline_panel.dart';
 | 
			
		||||
import '../globals.dart';
 | 
			
		||||
import '../models/TimelineIdentifiers.dart';
 | 
			
		||||
import '../models/group_data.dart';
 | 
			
		||||
import '../services/auth_service.dart';
 | 
			
		||||
import '../services/network_status_service.dart';
 | 
			
		||||
import '../services/timeline_manager.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
 | 
			
		||||
class HomeScreen extends StatefulWidget {
 | 
			
		||||
  const HomeScreen({super.key});
 | 
			
		||||
| 
						 | 
				
			
			@ -42,9 +43,15 @@ class _HomeScreenState extends State<HomeScreen> {
 | 
			
		|||
    _logger.finest('Build');
 | 
			
		||||
    final accountService = getIt<AccountsService>();
 | 
			
		||||
    final nss = getIt<NetworkStatusService>();
 | 
			
		||||
    final manager = context.watch<TimelineManager>();
 | 
			
		||||
    final manager = context
 | 
			
		||||
        .watch<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final groups = manager.getGroups().getValueOrElse(() => []).toList();
 | 
			
		||||
    groups.sort((g1, g2) => g1.name.compareTo(g2.name));
 | 
			
		||||
    if (!groups.contains(currentGroup)) {
 | 
			
		||||
      currentGroup = null;
 | 
			
		||||
    }
 | 
			
		||||
    final currentTimeline = TimelineIdentifiers(
 | 
			
		||||
      timeline: currentType,
 | 
			
		||||
      auxData: currentGroup?.id ?? '',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ import '../models/interaction_type_enum.dart';
 | 
			
		|||
import '../routes.dart';
 | 
			
		||||
import '../services/interactions_manager.dart';
 | 
			
		||||
import '../services/network_status_service.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
 | 
			
		||||
class InteractionsViewerScreen extends StatelessWidget {
 | 
			
		||||
  final String statusId;
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +47,10 @@ class InteractionsViewerScreen extends StatelessWidget {
 | 
			
		|||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final nss = getIt<NetworkStatusService>();
 | 
			
		||||
    final manager = context.watch<InteractionsManager>();
 | 
			
		||||
    final manager = context
 | 
			
		||||
        .watch<ActiveProfileSelector<InteractionsManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final connections = getInteractors(manager);
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: StandardAppBar.build(context, buildTitle(), actions: [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
import 'package:relatica/utils/clipboard_utils.dart';
 | 
			
		||||
import 'package:result_monad/result_monad.dart';
 | 
			
		||||
 | 
			
		||||
import '../controls/image_control.dart';
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +10,8 @@ import '../models/direct_message_thread.dart';
 | 
			
		|||
import '../models/exec_error.dart';
 | 
			
		||||
import '../services/auth_service.dart';
 | 
			
		||||
import '../services/direct_message_service.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
import '../utils/clipboard_utils.dart';
 | 
			
		||||
import '../utils/snackbar_builder.dart';
 | 
			
		||||
 | 
			
		||||
class MessageThreadScreen extends StatefulWidget {
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +31,10 @@ class _MessageThreadScreenState extends State<MessageThreadScreen> {
 | 
			
		|||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final service = context.watch<DirectMessageService>();
 | 
			
		||||
    final service = context
 | 
			
		||||
        .watch<ActiveProfileSelector<DirectMessageService>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final result = service.getThreadByParentUri(widget.parentThreadId);
 | 
			
		||||
    final title = result.fold(
 | 
			
		||||
        onSuccess: (t) => t.title.isEmpty ? 'Thread' : t.title,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,12 +9,16 @@ import '../globals.dart';
 | 
			
		|||
import '../routes.dart';
 | 
			
		||||
import '../services/direct_message_service.dart';
 | 
			
		||||
import '../services/network_status_service.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
import '../utils/dateutils.dart';
 | 
			
		||||
 | 
			
		||||
class MessagesScreen extends StatelessWidget {
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final service = context.watch<DirectMessageService>();
 | 
			
		||||
    final service = context
 | 
			
		||||
        .watch<ActiveProfileSelector<DirectMessageService>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final nss = getIt<NetworkStatusService>();
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: StandardAppBar.build(context, 'Direct Message Threads', actions: [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:go_router/go_router.dart';
 | 
			
		||||
import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart';
 | 
			
		||||
import 'package:relatica/utils/active_profile_selector.dart';
 | 
			
		||||
 | 
			
		||||
import '../controls/autocomplete/mention_autocomplete_options.dart';
 | 
			
		||||
import '../controls/padding.dart';
 | 
			
		||||
| 
						 | 
				
			
			@ -9,6 +8,7 @@ import '../controls/standard_appbar.dart';
 | 
			
		|||
import '../globals.dart';
 | 
			
		||||
import '../services/connections_manager.dart';
 | 
			
		||||
import '../services/direct_message_service.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
import '../utils/snackbar_builder.dart';
 | 
			
		||||
 | 
			
		||||
class MessagesNewThread extends StatelessWidget {
 | 
			
		||||
| 
						 | 
				
			
			@ -89,8 +89,10 @@ class MessagesNewThread extends StatelessWidget {
 | 
			
		|||
                        .andThen((manager) => manager.getByHandle(
 | 
			
		||||
                            receiverController.text.trim().substring(1)))
 | 
			
		||||
                        .andThenAsync((connection) async =>
 | 
			
		||||
                            getIt<DirectMessageService>()
 | 
			
		||||
                                .newThread(connection, replyController.text));
 | 
			
		||||
                            getIt<ActiveProfileSelector<DirectMessageService>>()
 | 
			
		||||
                                .activeEntry
 | 
			
		||||
                                .andThenAsync((dms) async => dms.newThread(
 | 
			
		||||
                                    connection, replyController.text)));
 | 
			
		||||
                result.match(onSuccess: (_) {
 | 
			
		||||
                  if (context.canPop()) {
 | 
			
		||||
                    context.pop();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import '../controls/timeline/post_control.dart';
 | 
			
		|||
import '../globals.dart';
 | 
			
		||||
import '../services/network_status_service.dart';
 | 
			
		||||
import '../services/timeline_manager.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
 | 
			
		||||
class PostScreen extends StatelessWidget {
 | 
			
		||||
  final String id;
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +23,10 @@ class PostScreen extends StatelessWidget {
 | 
			
		|||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final nss = getIt<NetworkStatusService>();
 | 
			
		||||
    final manager = context.watch<TimelineManager>();
 | 
			
		||||
    final manager = context
 | 
			
		||||
        .watch<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final body = manager.getPostTreeEntryBy(id).fold(
 | 
			
		||||
        onSuccess: (post) => PostControl(
 | 
			
		||||
              originalItem: post,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,15 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:go_router/go_router.dart';
 | 
			
		||||
import 'package:logging/logging.dart';
 | 
			
		||||
import 'package:relatica/models/auth/basic_credentials.dart';
 | 
			
		||||
import 'package:relatica/routes.dart';
 | 
			
		||||
import 'package:string_validator/string_validator.dart';
 | 
			
		||||
 | 
			
		||||
import '../controls/padding.dart';
 | 
			
		||||
import '../globals.dart';
 | 
			
		||||
import '../models/auth/basic_credentials.dart';
 | 
			
		||||
import '../models/auth/credentials_intf.dart';
 | 
			
		||||
import '../models/auth/oauth_credentials.dart';
 | 
			
		||||
import '../models/auth/profile.dart';
 | 
			
		||||
import '../routes.dart';
 | 
			
		||||
import '../services/auth_service.dart';
 | 
			
		||||
import '../utils/snackbar_builder.dart';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -300,7 +300,6 @@ class _SignInScreenState extends State<SignInScreen> {
 | 
			
		|||
 | 
			
		||||
                                if (confirm ?? false) {
 | 
			
		||||
                                  service.setActiveProfile(p);
 | 
			
		||||
                                  clearCaches();
 | 
			
		||||
                                  if (mounted) {
 | 
			
		||||
                                    context.goNamed(ScreenPaths.timelines);
 | 
			
		||||
                                  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ import '../globals.dart';
 | 
			
		|||
import '../models/TimelineIdentifiers.dart';
 | 
			
		||||
import '../services/network_status_service.dart';
 | 
			
		||||
import '../services/timeline_manager.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
 | 
			
		||||
class UserPostsScreen extends StatelessWidget {
 | 
			
		||||
  final String userId;
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +18,10 @@ class UserPostsScreen extends StatelessWidget {
 | 
			
		|||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final nss = getIt<NetworkStatusService>();
 | 
			
		||||
    final manager = context.watch<TimelineManager>();
 | 
			
		||||
    final manager = context
 | 
			
		||||
        .watch<ActiveProfileSelector<TimelineManager>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value;
 | 
			
		||||
    final timeline = TimelineIdentifiers.profile(userId);
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: StandardAppBar.build(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -316,7 +316,7 @@ class ConnectionsManager extends ChangeNotifier {
 | 
			
		|||
        .match(
 | 
			
		||||
      onSuccess: (groups) {
 | 
			
		||||
        _logger.finest('Got updated groups:${groups.map((e) => e.name)}');
 | 
			
		||||
        groupsRepo.clearGroups();
 | 
			
		||||
        groupsRepo.clearMyGroups();
 | 
			
		||||
        groupsRepo.addAllGroups(groups);
 | 
			
		||||
        if (withNotification) {
 | 
			
		||||
          notifyListeners();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:logging/logging.dart';
 | 
			
		||||
import 'package:relatica/services/network_status_service.dart';
 | 
			
		||||
import 'package:result_monad/result_monad.dart';
 | 
			
		||||
import 'package:uuid/uuid.dart';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -11,8 +10,10 @@ import '../friendica_client/paging_data.dart';
 | 
			
		|||
import '../globals.dart';
 | 
			
		||||
import '../models/exec_error.dart';
 | 
			
		||||
import '../models/user_notification.dart';
 | 
			
		||||
import '../utils/active_profile_selector.dart';
 | 
			
		||||
import 'auth_service.dart';
 | 
			
		||||
import 'direct_message_service.dart';
 | 
			
		||||
import 'network_status_service.dart';
 | 
			
		||||
 | 
			
		||||
class NotificationsManager extends ChangeNotifier {
 | 
			
		||||
  static final _logger = Logger('NotificationManager');
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +114,9 @@ class NotificationsManager extends ChangeNotifier {
 | 
			
		|||
      (key, value) => value.type == NotificationType.direct_message,
 | 
			
		||||
    );
 | 
			
		||||
    getIt<NetworkStatusService>().startNotificationUpdate();
 | 
			
		||||
    await getIt<DirectMessageService>().updateThreads();
 | 
			
		||||
    await getIt<ActiveProfileSelector<DirectMessageService>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .andThenSuccessAsync((dms) async => await dms.updateThreads());
 | 
			
		||||
    getIt<NetworkStatusService>().finishNotificationUpdate();
 | 
			
		||||
    for (final n in buildUnreadMessageNotifications()) {
 | 
			
		||||
      _notifications[n.id] = n;
 | 
			
		||||
| 
						 | 
				
			
			@ -180,8 +183,11 @@ class NotificationsManager extends ChangeNotifier {
 | 
			
		|||
 | 
			
		||||
  List<UserNotification> buildUnreadMessageNotifications() {
 | 
			
		||||
    final myId = getIt<AccountsService>().currentProfile.userId;
 | 
			
		||||
    final result =
 | 
			
		||||
        getIt<DirectMessageService>().getThreads(unreadyOnly: true).map((t) {
 | 
			
		||||
    final result = getIt<ActiveProfileSelector<DirectMessageService>>()
 | 
			
		||||
        .activeEntry
 | 
			
		||||
        .value
 | 
			
		||||
        .getThreads(unreadyOnly: true)
 | 
			
		||||
        .map((t) {
 | 
			
		||||
      final fromAccount = t.participants.firstWhere((p) => p.id != myId);
 | 
			
		||||
      final latestMessage =
 | 
			
		||||
          t.messages.reduce((s, m) => s.createdAt > m.createdAt ? s : m);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
 | 
			
		|||
import 'package:logging/logging.dart';
 | 
			
		||||
import 'package:result_monad/result_monad.dart';
 | 
			
		||||
 | 
			
		||||
import '../data/interfaces/groups_repo.intf.dart';
 | 
			
		||||
import '../friendica_client/friendica_client.dart';
 | 
			
		||||
import '../globals.dart';
 | 
			
		||||
import '../models/TimelineIdentifiers.dart';
 | 
			
		||||
| 
						 | 
				
			
			@ -24,24 +25,27 @@ enum TimelineRefreshType {
 | 
			
		|||
class TimelineManager extends ChangeNotifier {
 | 
			
		||||
  static final _logger = Logger('$TimelineManager');
 | 
			
		||||
 | 
			
		||||
  final IGroupsRepo groupsRepo;
 | 
			
		||||
  final EntryManagerService entryManagerService;
 | 
			
		||||
 | 
			
		||||
  final cachedTimelines = <TimelineIdentifiers, Timeline>{};
 | 
			
		||||
 | 
			
		||||
  final _groups = <String, GroupData>{};
 | 
			
		||||
  TimelineManager(this.groupsRepo, this.entryManagerService);
 | 
			
		||||
 | 
			
		||||
  void clear() {
 | 
			
		||||
    cachedTimelines.clear();
 | 
			
		||||
    _groups.clear();
 | 
			
		||||
    getIt<EntryManagerService>().clear();
 | 
			
		||||
    entryManagerService.clear();
 | 
			
		||||
    groupsRepo.clearMyGroups();
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Result<List<GroupData>, ExecError> getGroups() {
 | 
			
		||||
    if (_groups.isEmpty) {
 | 
			
		||||
    if (groupsRepo.getMyGroups().isEmpty) {
 | 
			
		||||
      _refreshGroupData();
 | 
			
		||||
      return Result.ok([]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Result.ok(_groups.values.toList());
 | 
			
		||||
    return Result.ok(groupsRepo.getMyGroups());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<void> _refreshGroupData() async {
 | 
			
		||||
| 
						 | 
				
			
			@ -50,10 +54,7 @@ class TimelineManager extends ChangeNotifier {
 | 
			
		|||
        .getGroups()
 | 
			
		||||
        .match(
 | 
			
		||||
      onSuccess: (groups) {
 | 
			
		||||
        _groups.clear();
 | 
			
		||||
        for (final group in groups) {
 | 
			
		||||
          _groups[group.id] = group;
 | 
			
		||||
        }
 | 
			
		||||
        groupsRepo.addAllGroups(groups);
 | 
			
		||||
        notifyListeners();
 | 
			
		||||
      },
 | 
			
		||||
      onError: (error) {
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +70,7 @@ class TimelineManager extends ChangeNotifier {
 | 
			
		|||
    required NewEntryMediaItems newMediaItems,
 | 
			
		||||
    required List<ImageEntry> existingMediaItems,
 | 
			
		||||
  }) async {
 | 
			
		||||
    final result = await getIt<EntryManagerService>().createNewStatus(
 | 
			
		||||
    final result = await entryManagerService.createNewStatus(
 | 
			
		||||
      text,
 | 
			
		||||
      spoilerText: spoilerText,
 | 
			
		||||
      inReplyToId: inReplyToId,
 | 
			
		||||
| 
						 | 
				
			
			@ -85,12 +86,12 @@ class TimelineManager extends ChangeNotifier {
 | 
			
		|||
 | 
			
		||||
  Result<TimelineEntry, ExecError> getEntryById(String id) {
 | 
			
		||||
    _logger.finest('Getting entry for $id');
 | 
			
		||||
    return getIt<EntryManagerService>().getEntryById(id);
 | 
			
		||||
    return entryManagerService.getEntryById(id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FutureResult<bool, ExecError> deleteEntryById(String id) async {
 | 
			
		||||
    _logger.finest('Delete entry for $id');
 | 
			
		||||
    final result = await getIt<EntryManagerService>().deleteEntryById(id);
 | 
			
		||||
    final result = await entryManagerService.deleteEntryById(id);
 | 
			
		||||
 | 
			
		||||
    if (result.isSuccess) {
 | 
			
		||||
      for (final t in cachedTimelines.values) {
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +104,7 @@ class TimelineManager extends ChangeNotifier {
 | 
			
		|||
 | 
			
		||||
  Result<EntryTreeItem, ExecError> getPostTreeEntryBy(String id) {
 | 
			
		||||
    _logger.finest('Getting post for $id');
 | 
			
		||||
    return getIt<EntryManagerService>().getPostTreeEntryBy(id);
 | 
			
		||||
    return entryManagerService.getPostTreeEntryBy(id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // refresh timeline gets statuses newer than the newest in that timeline
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +124,7 @@ class TimelineManager extends ChangeNotifier {
 | 
			
		|||
  /// id is the id of a post or comment in the chain, including the original post.
 | 
			
		||||
  FutureResult<EntryTreeItem, ExecError> refreshStatusChain(String id) async {
 | 
			
		||||
    _logger.finest('Refreshing post $id');
 | 
			
		||||
    final result = await getIt<EntryManagerService>().refreshStatusChain(id);
 | 
			
		||||
    final result = await entryManagerService.refreshStatusChain(id);
 | 
			
		||||
    if (result.isSuccess) {
 | 
			
		||||
      for (final t in cachedTimelines.values) {
 | 
			
		||||
        t.addOrUpdate([result.value]);
 | 
			
		||||
| 
						 | 
				
			
			@ -134,7 +135,7 @@ class TimelineManager extends ChangeNotifier {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  FutureResult<EntryTreeItem, ExecError> resharePost(String id) async {
 | 
			
		||||
    final result = await getIt<EntryManagerService>().resharePost(id);
 | 
			
		||||
    final result = await entryManagerService.resharePost(id);
 | 
			
		||||
    if (result.isSuccess) {
 | 
			
		||||
      for (final t in cachedTimelines.values) {
 | 
			
		||||
        t.addOrUpdate([result.value]);
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +146,7 @@ class TimelineManager extends ChangeNotifier {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  FutureResult<bool, ExecError> unResharePost(String id) async {
 | 
			
		||||
    final result = await getIt<EntryManagerService>().unResharePost(id);
 | 
			
		||||
    final result = await entryManagerService.unResharePost(id);
 | 
			
		||||
    if (result.isSuccess) {
 | 
			
		||||
      for (final t in cachedTimelines.values) {
 | 
			
		||||
        t.removeTimelineEntry(id);
 | 
			
		||||
| 
						 | 
				
			
			@ -179,9 +180,8 @@ class TimelineManager extends ChangeNotifier {
 | 
			
		|||
        highestId = timeline.highestStatusId;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    (await getIt<EntryManagerService>()
 | 
			
		||||
            .updateTimeline(type, lowestId, highestId))
 | 
			
		||||
        .match(onSuccess: (posts) {
 | 
			
		||||
    (await entryManagerService.updateTimeline(type, lowestId, highestId)).match(
 | 
			
		||||
        onSuccess: (posts) {
 | 
			
		||||
      _logger.finest('Posts returned for adding to $type: ${posts.length}');
 | 
			
		||||
      timeline.addOrUpdate(posts);
 | 
			
		||||
      notifyListeners();
 | 
			
		||||
| 
						 | 
				
			
			@ -193,8 +193,7 @@ class TimelineManager extends ChangeNotifier {
 | 
			
		|||
  FutureResult<EntryTreeItem, ExecError> toggleFavorited(
 | 
			
		||||
      String id, bool newStatus) async {
 | 
			
		||||
    _logger.finest('Attempting toggling favorite $id to $newStatus');
 | 
			
		||||
    final result =
 | 
			
		||||
        await getIt<EntryManagerService>().toggleFavorited(id, newStatus);
 | 
			
		||||
    final result = await entryManagerService.toggleFavorited(id, newStatus);
 | 
			
		||||
    if (result.isFailure) {
 | 
			
		||||
      _logger.finest('Error toggling favorite $id: ${result.error}');
 | 
			
		||||
      return result;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue