diff --git a/.github/workflows/android-internal-release.yml b/.github/workflows/android-internal-release.yml index 9a872738..f04a684c 100644 --- a/.github/workflows/android-internal-release.yml +++ b/.github/workflows/android-internal-release.yml @@ -25,8 +25,10 @@ jobs: fetch-depth: 0 - name: Setup JDK 17 - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: + distribution: "temurin" + cache: "gradle" java-version: 17 - name: Setup Flutter diff --git a/analysis_options.yaml b/analysis_options.yaml index f230517c..a4679e19 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,7 +1,34 @@ -include: package:flutter_lints/flutter.yaml +include: + - package:very_good_analysis/analysis_options.yaml + - package:flutter_lints/flutter.yaml formatter: page_width: 130 analyzer: errors: + avoid_catches_without_on_clauses: ignore + avoid_dynamic_calls: ignore + cascade_invocations: ignore + inference_failure_on_function_invocation: ignore + inference_failure_on_instance_creation: ignore invalid_annotation_target: ignore + lines_longer_than_80_chars: ignore + comment_references: ignore # enable when starting documentation + public_member_api_docs: ignore # enable when starting documentation + sort_pub_dependencies: ignore + prefer_null_aware_method_calls: ignore + strict_raw_type: ignore + avoid_equals_and_hash_code_on_mutable_classes: ignore + inference_failure_on_function_return_type: ignore + inference_failure_on_untyped_parameter: ignore + flutter_style_todos: ignore + specify_nonobvious_property_types: ignore + unnecessary_null_checks: ignore + sort_constructors_first: ignore + unawaited_futures: ignore + avoid_positional_boolean_parameters: ignore + use_setters_to_change_properties: ignore + prefer_asserts_with_message: ignore + document_ignores: ignore + one_member_abstracts: ignore + avoid_bool_literals_in_conditional_expressions: ignore diff --git a/android/gradle.properties b/android/gradle.properties index ff22b9ee..7cf4d885 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,4 +1,5 @@ org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true -kotlin.jvm.target.validation.mode=IGNORE \ No newline at end of file +kotlin.jvm.target.validation.mode=IGNORE +org.gradle.caching=true \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 0e8ef2f8..d4641b33 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,44 +3,36 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart' as riverpod; -import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:fvp/fvp.dart' as fvp; -import 'src/core/di/service_locator.dart'; -import 'src/core/theme/data/models/app_theme.dart'; -import 'src/core/utils/logging/logging.dart'; -import 'src/core/utils/logging/riverpod_logger.dart'; -import 'src/sprk_app.dart'; +import 'package:sparksocial/src/core/di/service_locator.dart'; +import 'package:sparksocial/src/core/theme/data/models/app_theme.dart'; +import 'package:sparksocial/src/core/utils/logging/logging.dart'; +import 'package:sparksocial/src/core/utils/logging/riverpod_logger.dart'; +import 'package:sparksocial/src/sprk_app.dart'; // Global RouteObserver instance final RouteObserver> routeObserver = RouteObserver>(); void main() async { - // Preserve the native splash screen - WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); - FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); - - await dotenv.load(fileName: ".env"); - SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); + WidgetsFlutterBinding.ensureInitialized(); - // Initialize IMGLY Video Editor SDK - // Note: You need to add a license file to assets folder and reference it in pubspec.yaml - // VESDK.unlockWithLicense("assets/licenses/vesdk_license"); + await dotenv.load(); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); // Force dark status bar and navigation bar SystemChrome.setSystemUIOverlayStyle(AppTheme.darkSystemUiStyle); fvp.registerWith(); - // Initialize dependencies for new architecture - await configureDependencies(); + await initServiceLocator(); // Setup logging for production/debug _setupLogging(); // Create a ProviderContainer with the Riverpod logger final container = riverpod.ProviderContainer(observers: [SparkRiverpodLogger()]); - runApp(riverpod.UncontrolledProviderScope(container: container, child: SprkApp())); + runApp(riverpod.UncontrolledProviderScope(container: container, child: const SprkApp())); } /// Setup logging framework based on environment diff --git a/lib/src/core/auth/data/models/login_result.dart b/lib/src/core/auth/data/models/login_result.dart index 3387aaa7..b5b36837 100644 --- a/lib/src/core/auth/data/models/login_result.dart +++ b/lib/src/core/auth/data/models/login_result.dart @@ -6,17 +6,16 @@ part 'login_result.freezed.dart'; /// Result of a login attempt @freezed class LoginResult with _$LoginResult { - const LoginResult._(); const factory LoginResult({ required LoginStatus status, String? error, }) = _LoginResult; + const LoginResult._(); factory LoginResult.success() => const LoginResult(status: LoginStatus.success); factory LoginResult.failed(String error) => LoginResult(status: LoginStatus.failed, error: error); factory LoginResult.codeRequired(String error) => LoginResult(status: LoginStatus.codeRequired, error: error); - bool get isSuccess => status == LoginStatus.success; bool get isCodeRequired => status == LoginStatus.codeRequired; -} \ No newline at end of file +} diff --git a/lib/src/core/auth/data/repositories/auth_repository_impl.dart b/lib/src/core/auth/data/repositories/auth_repository_impl.dart index 353ca8f4..165de4ae 100644 --- a/lib/src/core/auth/data/repositories/auth_repository_impl.dart +++ b/lib/src/core/auth/data/repositories/auth_repository_impl.dart @@ -1,24 +1,30 @@ -import 'dart:convert'; import 'dart:async'; +import 'dart:convert'; import 'package:atproto/atproto.dart'; import 'package:atproto/core.dart'; import 'package:get_it/get_it.dart'; import 'package:http/http.dart' as http; + import 'package:sparksocial/src/core/auth/data/models/login_result.dart'; import 'package:sparksocial/src/core/auth/data/repositories/auth_repository.dart'; import 'package:sparksocial/src/core/config/app_config.dart'; import 'package:sparksocial/src/core/storage/storage.dart'; import 'package:sparksocial/src/core/utils/logging/log_service.dart'; +import 'package:sparksocial/src/core/utils/logging/logger.dart'; /// Implementation of the authentication repository for AT Protocol class AuthRepositoryImpl implements AuthRepository { + AuthRepositoryImpl() { + _logger.i('Initializing AuthRepository'); + _initialize(); + } Session? _session; ATProto? _atProto; String? _dmAccessToken; String? _dmRefreshToken; - final _logger = GetIt.instance().getLogger('AuthRepository'); + final SparkLogger _logger = GetIt.instance().getLogger('AuthRepository'); final Completer _initCompleter = Completer(); Future get initializationComplete => _initCompleter.future; @@ -38,11 +44,6 @@ class AuthRepositoryImpl implements AuthRepository { @override String? get dmRefreshToken => _dmRefreshToken; - AuthRepositoryImpl() { - _logger.i('Initializing AuthRepository'); - _initialize(); - } - Future _initialize() async { try { await _loadSavedSession(); @@ -63,9 +64,9 @@ class AuthRepositoryImpl implements AuthRepository { return null; } - final pdsService = services.firstWhere((s) => s['id'] == '#atproto_pds', orElse: () => {}); + final pdsService = services.firstWhere((s) => s['id'] == '#atproto_pds'); - final String? pdsUrl = pdsService['serviceEndpoint'] as String?; + final pdsUrl = pdsService['serviceEndpoint'] as String?; if (pdsUrl == null) { return null; } @@ -91,8 +92,8 @@ class AuthRepositoryImpl implements AuthRepository { if (response.statusCode == 200) { final data = jsonDecode(response.body); - _dmAccessToken = data['accessJwt']; - _dmRefreshToken = data['refreshJwt']; + _dmAccessToken = data['accessJwt'] as String?; + _dmRefreshToken = data['refreshJwt'] as String?; await StorageManager.instance.secure.setString(StorageKeys.dmAccessToken, _dmAccessToken!); await StorageManager.instance.secure.setString(StorageKeys.dmRefreshToken, _dmRefreshToken!); _logger.i('Logged in to message service successfully'); @@ -115,7 +116,7 @@ class AuthRepositoryImpl implements AuthRepository { return; } - _session = Session.fromJson(json.decode(savedSessionJson)); + _session = Session.fromJson(json.decode(savedSessionJson) as Map); if (_session == null) { _logger.w('Failed to parse saved session'); return; @@ -147,8 +148,8 @@ class AuthRepositoryImpl implements AuthRepository { if (response.statusCode == 200) { final data = jsonDecode(response.body); - _dmAccessToken = data['access_token']; - _dmRefreshToken = data['refresh_token']; + _dmAccessToken = data['access_token'] as String?; + _dmRefreshToken = data['refresh_token'] as String?; } else { if (!await refreshDMToken()) { throw Exception('Failed to refresh DM token'); @@ -178,10 +179,10 @@ class AuthRepositoryImpl implements AuthRepository { if (response.statusCode == 200) { final data = jsonDecode(response.body); - await StorageManager.instance.secure.setString(StorageKeys.dmAccessToken, data['access_token']); - _dmAccessToken = data['access_token']; - _dmRefreshToken = data['refresh_token']; - await StorageManager.instance.secure.setString(StorageKeys.dmRefreshToken, data['refresh_token']); + await StorageManager.instance.secure.setString(StorageKeys.dmAccessToken, data['access_token'] as String? ?? ''); + _dmAccessToken = data['access_token'] as String?; + _dmRefreshToken = data['refresh_token'] as String?; + await StorageManager.instance.secure.setString(StorageKeys.dmRefreshToken, data['refresh_token'] as String? ?? ''); return true; } _logger.e('Failed to refresh DM token: ${response.statusCode} - ${response.body}'); @@ -196,13 +197,13 @@ class AuthRepositoryImpl implements AuthRepository { } _logger.i('Refreshing session for user: ${_session!.handle}'); - String? service = _session!.didDoc != null ? _extractPdsDomain(_session!.didDoc!) : null; + var service = _session!.didDoc != null ? _extractPdsDomain(_session!.didDoc!) : null; if (service == null) { _logger.d('Fetching DID document from PLC directory'); final didDocResponse = await http.get(Uri.parse('https://plc.directory/${_session!.did}')); if (didDocResponse.statusCode == 200) { - service = _extractPdsDomain(json.decode(didDocResponse.body)); + service = _extractPdsDomain(json.decode(didDocResponse.body) as Map); } } @@ -263,13 +264,13 @@ class AuthRepositoryImpl implements AuthRepository { Future login(String handle, String password, {String? authCode}) async { try { _logger.i('Login attempt for user: $handle'); - ATProto at = ATProto.anonymous(service: 'pds.sprk.so'); + final at = ATProto.anonymous(service: 'pds.sprk.so'); _logger.d('Resolving handle: $handle'); final didRes = await at.identity.resolveHandle(handle: handle); - String did = didRes.data.did; - _logger.d('Resolved DID: $did'); - - _logger.d('Fetching DID document'); + final did = didRes.data.did; + _logger + ..d('Resolved DID: $did') + ..d('Fetching DID document'); final didDocResponse = await http.get(Uri.parse('https://plc.directory/$did')); if (didDocResponse.statusCode != 200) { @@ -279,8 +280,8 @@ class AuthRepositoryImpl implements AuthRepository { final didDoc = json.decode(didDocResponse.body); - String? pdsUrl = - (didDoc['service'] as List).firstWhere((s) => s['id'] == '#atproto_pds', orElse: () => {})['serviceEndpoint'] + final pdsUrl = + (didDoc['service'] as List).firstWhere((s) => s['id'] == '#atproto_pds', orElse: () => '')['serviceEndpoint'] as String?; if (pdsUrl == null) { @@ -288,7 +289,7 @@ class AuthRepositoryImpl implements AuthRepository { throw Exception('PDS endpoint not found in DID document'); } - String pdsDomain = Uri.parse(pdsUrl).host; + final pdsDomain = Uri.parse(pdsUrl).host; _logger.d('Using PDS domain: $pdsDomain'); try { @@ -332,7 +333,7 @@ class AuthRepositoryImpl implements AuthRepository { Future<({bool success, String? error})> register(String handle, String email, String password, String? inviteCode) async { try { _logger.i('Registration attempt for handle: $handle, email: $email'); - ATProto at = ATProto.anonymous(service: 'pds.sprk.so'); + final at = ATProto.anonymous(service: 'pds.sprk.so'); _logger.d('Creating account'); final createResponse = await at.server.createAccount( handle: handle, diff --git a/lib/src/core/auth/data/repositories/identity_repository_impl.dart b/lib/src/core/auth/data/repositories/identity_repository_impl.dart index beec7a72..e608c580 100644 --- a/lib/src/core/auth/data/repositories/identity_repository_impl.dart +++ b/lib/src/core/auth/data/repositories/identity_repository_impl.dart @@ -8,9 +8,14 @@ import 'package:http/http.dart' as http; import 'package:sparksocial/src/core/auth/data/repositories/identity_repository.dart'; import 'package:sparksocial/src/core/storage/storage.dart'; import 'package:sparksocial/src/core/utils/logging/log_service.dart'; +import 'package:sparksocial/src/core/utils/logging/logger.dart'; /// Implementation of [IdentityRepository] with caching capabilities class IdentityRepositoryImpl implements IdentityRepository { + /// Creates a new [IdentityRepositoryImpl] instance and loads the cache + IdentityRepositoryImpl(this._storageManager) { + _loadCache(); + } final Map _didToHandleCache = {}; final Map _handleToDidCache = {}; final Map> _didDocCache = {}; @@ -18,12 +23,7 @@ class IdentityRepositoryImpl implements IdentityRepository { static const Duration _cacheExpiration = Duration(hours: 2); final StorageManager _storageManager; - final _logger = GetIt.instance().getLogger('IdentityRepository'); - - /// Creates a new [IdentityRepositoryImpl] instance and loads the cache - IdentityRepositoryImpl(this._storageManager) { - _loadCache(); - } + final SparkLogger _logger = GetIt.instance().getLogger('IdentityRepository'); Future _loadCache() async { try { @@ -55,7 +55,7 @@ class IdentityRepositoryImpl implements IdentityRepository { } void _loadDidToHandleCache(String jsonData) { - final Map data = json.decode(jsonData); + final data = json.decode(jsonData) as Map; _didToHandleCache.clear(); data.forEach((key, value) { @@ -66,7 +66,7 @@ class IdentityRepositoryImpl implements IdentityRepository { } void _loadHandleToDidCache(String jsonData) { - final Map data = json.decode(jsonData); + final data = json.decode(jsonData) as Map; _handleToDidCache.clear(); data.forEach((key, value) { @@ -77,7 +77,7 @@ class IdentityRepositoryImpl implements IdentityRepository { } void _loadDidDocCache(String jsonData) { - final Map data = json.decode(jsonData); + final data = json.decode(jsonData) as Map; _didDocCache.clear(); data.forEach((key, value) { @@ -147,7 +147,7 @@ class IdentityRepositoryImpl implements IdentityRepository { return null; } - for (var aka in alsoKnownAs) { + for (final aka in alsoKnownAs) { if (aka is String && aka.startsWith('at://')) { final handle = aka.replaceFirst('at://', ''); @@ -187,7 +187,7 @@ class IdentityRepositoryImpl implements IdentityRepository { } final didDoc = json.decode(response.body); - _didDocCache[did] = didDoc; + _didDocCache[did] = didDoc as Map; await _saveCache(); return didDoc; @@ -195,7 +195,7 @@ class IdentityRepositoryImpl implements IdentityRepository { @override Future?> resolveHandleToDidDoc(String handle) async { - String? did = _handleToDidCache[handle]; + var did = _handleToDidCache[handle]; if (did == null) { did = await resolveHandleToDid(handle); @@ -204,7 +204,7 @@ class IdentityRepositoryImpl implements IdentityRepository { } } - return await resolveDidToDidDoc(did); + return resolveDidToDidDoc(did); } @override @@ -237,7 +237,7 @@ class IdentityRepositoryImpl implements IdentityRepository { @override Future> resolveDidsToHandles(List dids) async { final results = {}; - final futures = []; + final futures = >[]; for (final did in dids) { if (_didToHandleCache.containsKey(did)) { @@ -248,6 +248,7 @@ class IdentityRepositoryImpl implements IdentityRepository { futures.add( resolveDidToHandle(did).then((handle) { results[did] = handle; + return null; }), ); } @@ -262,7 +263,7 @@ class IdentityRepositoryImpl implements IdentityRepository { @override Future> resolveHandlesToDids(List handles) async { final results = {}; - final futures = []; + final futures = >[]; for (final handle in handles) { if (_handleToDidCache.containsKey(handle)) { @@ -273,6 +274,7 @@ class IdentityRepositoryImpl implements IdentityRepository { futures.add( resolveHandleToDid(handle).then((did) { results[handle] = did; + return null; }), ); } diff --git a/lib/src/core/auth/data/repositories/onboarding_repository_impl.dart b/lib/src/core/auth/data/repositories/onboarding_repository_impl.dart index 915cbedc..b2a2ee47 100644 --- a/lib/src/core/auth/data/repositories/onboarding_repository_impl.dart +++ b/lib/src/core/auth/data/repositories/onboarding_repository_impl.dart @@ -4,22 +4,21 @@ import 'package:atproto/atproto.dart'; import 'package:atproto/core.dart'; import 'package:bluesky/bluesky.dart' as bs; import 'package:get_it/get_it.dart'; +import 'package:sparksocial/src/core/auth/data/repositories/auth_repository.dart'; +import 'package:sparksocial/src/core/auth/data/repositories/onboarding_repository.dart'; import 'package:sparksocial/src/core/network/atproto/data/models/actor_models.dart'; import 'package:sparksocial/src/core/network/atproto/data/models/graph_models.dart'; - import 'package:sparksocial/src/core/network/atproto/data/repositories/repo_repository.dart'; import 'package:sparksocial/src/core/utils/logging/log_service.dart'; -import 'package:sparksocial/src/core/auth/data/repositories/auth_repository.dart'; -import 'onboarding_repository.dart'; +import 'package:sparksocial/src/core/utils/logging/logger.dart'; class OnboardingRepositoryImpl implements OnboardingRepository { - final RepoRepository _repoRepository; - final AuthRepository _authRepository; - final _logger = GetIt.instance().getLogger('OnboardingRepository'); - OnboardingRepositoryImpl({required RepoRepository repoRepository, required AuthRepository authRepository}) : _repoRepository = repoRepository, _authRepository = authRepository; + final RepoRepository _repoRepository; + final AuthRepository _authRepository; + final SparkLogger _logger = GetIt.instance().getLogger('OnboardingRepository'); Session? get _session => _authRepository.session; ATProto? get _atproto => _authRepository.atproto; @@ -87,7 +86,7 @@ class OnboardingRepositoryImpl implements OnboardingRepository { } final record = { - '\$type': 'so.sprk.actor.profile', + r'$type': 'so.sprk.actor.profile', 'displayName': displayName, 'description': description, if (avatarField != null) 'avatar': avatarField, @@ -112,11 +111,11 @@ class OnboardingRepositoryImpl implements OnboardingRepository { // Convert raw data to our structured model final rawData = response.data.toJson(); - final List rawFollows = rawData['follows'] as List; + final rawFollows = rawData['follows'] as List; final follows = rawFollows .map( - (followData) => ProfileView.fromJson(followData), + (followData) => ProfileView.fromJson(followData as Map), ) .toList(); @@ -126,7 +125,7 @@ class OnboardingRepositoryImpl implements OnboardingRepository { @override Future createSparkFollow(String subject) async { final record = { - '\$type': 'so.sprk.graph.follow', + r'$type': 'so.sprk.graph.follow', 'subject': subject, 'createdAt': DateTime.now().toUtc().toIso8601String(), }; diff --git a/lib/src/core/config/app_config.dart b/lib/src/core/config/app_config.dart index 69630b13..26103193 100644 --- a/lib/src/core/config/app_config.dart +++ b/lib/src/core/config/app_config.dart @@ -23,7 +23,7 @@ class AppConfig { static int get apiTimeoutSeconds => _getIntValue('API_TIMEOUT_SECONDS', 30); /// Maximum upload file size in MB. - static double get maxUploadSizeMB => _getDoubleValue('MAX_UPLOAD_SIZE_MB', 100.0); + static double get maxUploadSizeMB => _getDoubleValue('MAX_UPLOAD_SIZE_MB', 100); /// The current application environment (development, production, etc.) static String get environment => _getStringValue('ENVIRONMENT', 'development'); diff --git a/lib/src/core/di/service_locator.dart b/lib/src/core/di/service_locator.dart index 4ef741c1..bd714698 100644 --- a/lib/src/core/di/service_locator.dart +++ b/lib/src/core/di/service_locator.dart @@ -1,23 +1,23 @@ import 'package:get_it/get_it.dart'; import 'package:sparksocial/src/core/auth/data/repositories/auth_repository_impl.dart'; +import 'package:sparksocial/src/core/auth/data/repositories/onboarding_repository.dart'; +import 'package:sparksocial/src/core/auth/data/repositories/onboarding_repository_impl.dart'; +import 'package:sparksocial/src/core/network/atproto/atproto.dart'; +import 'package:sparksocial/src/core/network/atproto/data/repositories/actor_repository_impl.dart'; +import 'package:sparksocial/src/core/network/atproto/data/repositories/graph_repository_impl.dart'; +import 'package:sparksocial/src/core/network/atproto/data/repositories/sprk_repository_impl.dart'; import 'package:sparksocial/src/core/network/messages/data/repository/messages_repository.dart'; import 'package:sparksocial/src/core/network/messages/data/repository/messages_repository_impl.dart'; import 'package:sparksocial/src/core/storage/cache/cache_manager_impl.dart'; import 'package:sparksocial/src/core/storage/cache/download_manager_interface.dart'; import 'package:sparksocial/src/core/storage/cache/sql_cache_interface.dart'; -import 'package:sparksocial/src/core/theme/data/repositories/theme_repository.dart'; -import 'package:sparksocial/src/core/theme/data/repositories/theme_repository_impl.dart'; import 'package:sparksocial/src/core/storage/preferences/settings_repository.dart'; -import 'package:sparksocial/src/features/auth/auth.dart'; +import 'package:sparksocial/src/core/storage/preferences/settings_repository_impl.dart'; import 'package:sparksocial/src/core/storage/storage.dart'; -import 'package:sparksocial/src/core/network/atproto/atproto.dart'; +import 'package:sparksocial/src/core/theme/data/repositories/theme_repository.dart'; +import 'package:sparksocial/src/core/theme/data/repositories/theme_repository_impl.dart'; import 'package:sparksocial/src/core/utils/logging/logging.dart'; -import 'package:sparksocial/src/core/network/atproto/data/repositories/sprk_repository_impl.dart'; -import 'package:sparksocial/src/core/storage/preferences/settings_repository_impl.dart'; -import 'package:sparksocial/src/core/auth/data/repositories/onboarding_repository.dart'; -import 'package:sparksocial/src/core/auth/data/repositories/onboarding_repository_impl.dart'; -import 'package:sparksocial/src/core/network/atproto/data/repositories/actor_repository_impl.dart'; -import 'package:sparksocial/src/core/network/atproto/data/repositories/graph_repository_impl.dart'; +import 'package:sparksocial/src/features/auth/auth.dart'; // This is the ONLY PLACE IN THE ENTIRE APP where implementations are imported // All the other files should import interfaces only (polymorphism) to keep everything decoupled diff --git a/lib/src/core/feed_algorithms/feed_following.dart b/lib/src/core/feed_algorithms/feed_following.dart index b44282fe..ef511e47 100644 --- a/lib/src/core/feed_algorithms/feed_following.dart +++ b/lib/src/core/feed_algorithms/feed_following.dart @@ -1,8 +1,8 @@ -import 'package:bluesky/bluesky.dart' as bsky; import 'package:atproto_core/atproto_core.dart'; +import 'package:bluesky/bluesky.dart' as bsky; import 'package:get_it/get_it.dart'; -import 'package:sparksocial/src/core/network/atproto/data/repositories/sprk_repository.dart'; import 'package:sparksocial/src/core/network/atproto/data/models/feed_models.dart'; +import 'package:sparksocial/src/core/network/atproto/data/repositories/sprk_repository.dart'; Future followingSkeletonFunction({int? limit, String? cursor}) async { limit ??= 10; diff --git a/lib/src/core/feed_algorithms/feed_for_you.dart b/lib/src/core/feed_algorithms/feed_for_you.dart index 51b3c797..80c385ad 100644 --- a/lib/src/core/feed_algorithms/feed_for_you.dart +++ b/lib/src/core/feed_algorithms/feed_for_you.dart @@ -1,5 +1,5 @@ -import 'package:bluesky/bluesky.dart' as bsky; import 'package:atproto_core/atproto_core.dart'; +import 'package:bluesky/bluesky.dart' as bsky; import 'package:get_it/get_it.dart'; import 'package:sparksocial/src/core/network/atproto/data/models/feed_models.dart'; import 'package:sparksocial/src/core/network/atproto/data/repositories/sprk_repository.dart'; diff --git a/lib/src/core/feed_algorithms/feed_latest_sprk.dart b/lib/src/core/feed_algorithms/feed_latest_sprk.dart index fbfd8d7c..11a181e1 100644 --- a/lib/src/core/feed_algorithms/feed_latest_sprk.dart +++ b/lib/src/core/feed_algorithms/feed_latest_sprk.dart @@ -1,8 +1,8 @@ import 'dart:convert'; import 'package:atproto_core/atproto_core.dart'; -import 'package:sparksocial/src/core/network/atproto/data/models/feed_models.dart'; import 'package:get_it/get_it.dart'; +import 'package:sparksocial/src/core/network/atproto/data/models/feed_models.dart'; import 'package:sparksocial/src/core/network/atproto/data/repositories/sprk_repository.dart'; Future latestSprkSkeletonFunction({int? limit, String? cursor}) async { @@ -21,7 +21,7 @@ Future latestSprkSkeletonFunction({int? limit, String? cursor}) as }, // need to call the API directly because latest-sprk is not a parsable AtUri service: 'feeds.sprk.so', to: (jsonMap) => jsonMap, - adaptor: (uint8) => jsonDecode(utf8.decode(uint8)), + adaptor: (uint8) => jsonDecode(utf8.decode(uint8 as List)) as Map, ); final feedData = feedGenRes.data['feed'] as List?; final uris = feedData?.map((item) => item['post'] as String).toList() ?? []; diff --git a/lib/src/core/feed_algorithms/feed_mutuals.dart b/lib/src/core/feed_algorithms/feed_mutuals.dart index df386445..26c5fe50 100644 --- a/lib/src/core/feed_algorithms/feed_mutuals.dart +++ b/lib/src/core/feed_algorithms/feed_mutuals.dart @@ -2,5 +2,7 @@ import 'package:sparksocial/src/core/network/atproto/data/models/feed_models.dar Future mutualsSkeletonFunction({int? limit, String? cursor}) async { limit ??= 10; - return FeedSkeleton(feed: [],); // TODO: implement + return const FeedSkeleton( + feed: [], + ); // TODO: implement } diff --git a/lib/src/core/feed_algorithms/feed_shared.dart b/lib/src/core/feed_algorithms/feed_shared.dart index 63deaf03..51eb2a53 100644 --- a/lib/src/core/feed_algorithms/feed_shared.dart +++ b/lib/src/core/feed_algorithms/feed_shared.dart @@ -3,7 +3,7 @@ import 'package:sparksocial/src/core/network/atproto/data/models/feed_models.dar Future sharedSkeletonFunction({int? limit, String? cursor}) async { limit ??= 10; - return FeedSkeleton(feed: []); // TODO: implement + return const FeedSkeleton(feed: []); // TODO: implement } Future> sharedExtraInfoFunction(List uris) async { diff --git a/lib/src/core/feed_algorithms/hardcoded_feed_algorithm.dart b/lib/src/core/feed_algorithms/hardcoded_feed_algorithm.dart index 5b80ace8..a80edca3 100644 --- a/lib/src/core/feed_algorithms/hardcoded_feed_algorithm.dart +++ b/lib/src/core/feed_algorithms/hardcoded_feed_algorithm.dart @@ -1,10 +1,10 @@ import 'package:atproto/core.dart'; -import 'package:sparksocial/src/core/network/atproto/data/models/feed_models.dart'; import 'package:sparksocial/src/core/feed_algorithms/feed_following.dart'; import 'package:sparksocial/src/core/feed_algorithms/feed_for_you.dart'; -import 'package:sparksocial/src/core/feed_algorithms/feed_mutuals.dart'; import 'package:sparksocial/src/core/feed_algorithms/feed_latest_sprk.dart'; +import 'package:sparksocial/src/core/feed_algorithms/feed_mutuals.dart'; import 'package:sparksocial/src/core/feed_algorithms/feed_shared.dart'; +import 'package:sparksocial/src/core/network/atproto/data/models/feed_models.dart'; typedef SkeletonFunction = Future Function({int? limit, String? cursor}); typedef ExtraInfoFunction = Future> Function(List uris); @@ -36,7 +36,10 @@ class HardCodedFeedAlgorithm { switch (feed) { case HardCodedFeedEnum.shared: return sharedExtraInfo; - default: + case HardCodedFeedEnum.following: + case HardCodedFeedEnum.mutuals: + case HardCodedFeedEnum.forYou: + case HardCodedFeedEnum.latestSprk: return null; } } diff --git a/lib/src/core/network/atproto/atproto.dart b/lib/src/core/network/atproto/atproto.dart index 12a45031..1fa230bf 100644 --- a/lib/src/core/network/atproto/atproto.dart +++ b/lib/src/core/network/atproto/atproto.dart @@ -1,8 +1,6 @@ -library; - export 'data/models/models.dart'; -export 'data/repositories/sprk_repository.dart'; export 'data/repositories/actor_repository.dart'; -export 'data/repositories/repo_repository.dart'; export 'data/repositories/feed_repository.dart'; export 'data/repositories/graph_repository.dart'; +export 'data/repositories/repo_repository.dart'; +export 'data/repositories/sprk_repository.dart'; diff --git a/lib/src/core/network/atproto/data/models/actor_models.dart b/lib/src/core/network/atproto/data/models/actor_models.dart index a596bac9..3f41edfd 100644 --- a/lib/src/core/network/atproto/data/models/actor_models.dart +++ b/lib/src/core/network/atproto/data/models/actor_models.dart @@ -7,7 +7,6 @@ part 'actor_models.g.dart'; @freezed class ActorViewer with _$ActorViewer { - const ActorViewer._(); @JsonSerializable(explicitToJson: true) const factory ActorViewer({ bool? muted, @@ -19,18 +18,19 @@ class ActorViewer with _$ActorViewer { @AtUriConverter() AtUri? followedBy, KnownFollowers? followers, }) = _ActorViewer; + const ActorViewer._(); factory ActorViewer.fromJson(Map json) => _$ActorViewerFromJson(json); } @freezed class KnownFollowers with _$KnownFollowers { - const KnownFollowers._(); @JsonSerializable(explicitToJson: true) const factory KnownFollowers({ required int count, required List followersDids, // to avoid circular dependency }) = _KnownFollowers; + const KnownFollowers._(); factory KnownFollowers.fromJson(Map json) => switch (json) { {'followers': final List profiles, 'count': final int count} => _$KnownFollowersFromJson({ @@ -43,7 +43,6 @@ class KnownFollowers with _$KnownFollowers { @freezed class ProfileViewBasic with _$ProfileViewBasic { - const ProfileViewBasic._(); @JsonSerializable(explicitToJson: true) const factory ProfileViewBasic({ required String did, @@ -54,13 +53,13 @@ class ProfileViewBasic with _$ProfileViewBasic { ActorViewer? viewer, List? stories, }) = _ProfileViewBasic; + const ProfileViewBasic._(); factory ProfileViewBasic.fromJson(Map json) => _$ProfileViewBasicFromJson(json); } @freezed class ProfileView with _$ProfileView { - const ProfileView._(); @JsonSerializable(explicitToJson: true) const factory ProfileView({ required String did, @@ -74,6 +73,7 @@ class ProfileView with _$ProfileView { List