[READ ONLY MIRROR] Open Source TikTok alternative built on AT Protocol github.com/sprksocial/client
flutter atproto video dart
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: legal page and beta disclaimer

+129 -9
+3 -7
ios/Runner.xcodeproj/project.pbxproj
··· 3 3 archiveVersion = 1; 4 4 classes = { 5 5 }; 6 - objectVersion = 60; 6 + objectVersion = 54; 7 7 objects = { 8 8 9 9 /* Begin PBXBuildFile section */ ··· 253 253 ); 254 254 mainGroup = 97C146E51CF9000F007C117D; 255 255 packageReferences = ( 256 - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, 256 + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, 257 257 ); 258 258 productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 259 259 projectDirPath = ""; ··· 313 313 inputFileListPaths = ( 314 314 "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", 315 315 ); 316 - inputPaths = ( 317 - ); 318 316 name = "[CP] Embed Pods Frameworks"; 319 317 outputFileListPaths = ( 320 318 "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", 321 - ); 322 - outputPaths = ( 323 319 ); 324 320 runOnlyForDeploymentPostprocessing = 0; 325 321 shellPath = /bin/sh; ··· 775 771 /* End XCConfigurationList section */ 776 772 777 773 /* Begin XCLocalSwiftPackageReference section */ 778 - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { 774 + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { 779 775 isa = XCLocalSwiftPackageReference; 780 776 relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; 781 777 };
+1
lib/src/core/routing/app_router.dart
··· 72 72 AutoRoute(page: EditProfileRoute.page, path: '/profile-editor'), 73 73 74 74 AutoRoute(page: SettingsRoute.page, path: '/settings'), 75 + AutoRoute(page: LegalRoute.page, path: '/settings/legal'), 75 76 AutoRoute(page: FeedListRoute.page, path: '/settings/feeds'), 76 77 AutoRoute(page: LabelerManagementRoute.page, path: '/settings/labelers'), 77 78 AutoRoute(page: BlocksRoute.page, path: '/settings/blocks'),
+1
lib/src/core/routing/pages.dart
··· 29 29 export 'package:spark/src/features/search/ui/pages/search_page.dart'; 30 30 export 'package:spark/src/features/settings/ui/pages/feed_list_page.dart'; 31 31 export 'package:spark/src/features/settings/ui/pages/labeler_label_settings_page.dart'; 32 + export 'package:spark/src/features/settings/ui/pages/legal_page.dart'; 32 33 export 'package:spark/src/features/settings/ui/pages/labeler_management_page.dart'; 33 34 export 'package:spark/src/features/settings/ui/pages/settings_page.dart'; 34 35 export 'package:spark/src/features/sound/ui/pages/sound_page.dart';
+3 -2
lib/src/features/auth/ui/pages/register_page.dart
··· 171 171 ), 172 172 const SizedBox(height: 12), 173 173 Text( 174 - 'Share videos, connect with friends,\n' 175 - 'and take back your timeline.', 174 + 'Spark is currently in public beta.\n' 175 + 'We value your feedback and are still \n' 176 + 'rapidly improving.', 176 177 style: AppTypography.textMediumMedium.copyWith( 177 178 color: colorScheme.onSurfaceVariant, 178 179 height: 1.5,
+98
lib/src/features/settings/ui/pages/legal_page.dart
··· 1 + import 'package:auto_route/auto_route.dart'; 2 + import 'package:fluentui_system_icons/fluentui_system_icons.dart'; 3 + import 'package:flutter/material.dart'; 4 + import 'package:get_it/get_it.dart'; 5 + import 'package:spark/src/core/design_system/components/atoms/buttons/app_leading_button.dart'; 6 + import 'package:spark/src/core/utils/logging/log_service.dart'; 7 + import 'package:url_launcher/url_launcher.dart'; 8 + 9 + @RoutePage() 10 + class LegalPage extends StatelessWidget { 11 + const LegalPage({super.key}); 12 + 13 + static const List<({String title, String path})> _legalLinks = [ 14 + (title: 'Privacy Policy', path: '/privacy'), 15 + (title: 'Terms of Service', path: '/terms'), 16 + (title: 'Support', path: '/support'), 17 + ]; 18 + 19 + static final Uri _baseUri = Uri.parse('https://sprk.so'); 20 + 21 + Future<void> _openLink(BuildContext context, String path) async { 22 + final logger = GetIt.instance<LogService>().getLogger('LegalPage'); 23 + final uri = _baseUri.replace(path: path); 24 + 25 + try { 26 + final didLaunch = await launchUrl( 27 + uri, 28 + mode: LaunchMode.externalApplication, 29 + ); 30 + 31 + if (!didLaunch && context.mounted) { 32 + ScaffoldMessenger.of(context).showSnackBar( 33 + const SnackBar(content: Text('Unable to open link right now.')), 34 + ); 35 + } 36 + } catch (error, stackTrace) { 37 + logger.e( 38 + 'Failed to launch legal URL: $uri', 39 + error: error, 40 + stackTrace: stackTrace, 41 + ); 42 + 43 + if (context.mounted) { 44 + ScaffoldMessenger.of(context).showSnackBar( 45 + const SnackBar(content: Text('Unable to open link right now.')), 46 + ); 47 + } 48 + } 49 + } 50 + 51 + @override 52 + Widget build(BuildContext context) { 53 + final colorScheme = Theme.of(context).colorScheme; 54 + 55 + return Scaffold( 56 + backgroundColor: colorScheme.surface, 57 + appBar: AppBar( 58 + backgroundColor: colorScheme.surface, 59 + elevation: 0, 60 + scrolledUnderElevation: 0, 61 + leading: const AppLeadingButton(), 62 + title: const Text('Legal'), 63 + centerTitle: true, 64 + ), 65 + body: ListView.separated( 66 + padding: const EdgeInsets.all(16), 67 + itemCount: _legalLinks.length, 68 + separatorBuilder: (_, _) => const SizedBox(height: 16), 69 + itemBuilder: (context, index) { 70 + final link = _legalLinks[index]; 71 + 72 + return Container( 73 + decoration: BoxDecoration( 74 + color: colorScheme.surfaceContainerHighest.withValues(alpha: 0.5), 75 + borderRadius: BorderRadius.circular(12), 76 + ), 77 + child: ListTile( 78 + title: Text( 79 + link.title, 80 + style: const TextStyle( 81 + fontSize: 16, 82 + fontWeight: FontWeight.bold, 83 + ), 84 + ), 85 + subtitle: Text('sprk.so${link.path}'), 86 + trailing: const Icon(FluentIcons.open_24_regular), 87 + contentPadding: const EdgeInsets.symmetric( 88 + horizontal: 16, 89 + vertical: 4, 90 + ), 91 + onTap: () => _openLink(context, link.path), 92 + ), 93 + ); 94 + }, 95 + ), 96 + ); 97 + } 98 + }
+23
lib/src/features/settings/ui/pages/settings_page.dart
··· 311 311 decoration: BoxDecoration( 312 312 color: Theme.of( 313 313 context, 314 + ).colorScheme.surfaceContainerHighest.withValues(alpha: 0.5), 315 + borderRadius: BorderRadius.circular(12), 316 + ), 317 + child: ListTile( 318 + title: const Text( 319 + 'Legal', 320 + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), 321 + ), 322 + trailing: const Icon(FluentIcons.document_24_regular), 323 + onTap: () => context.router.push(const LegalRoute()), 324 + contentPadding: const EdgeInsets.symmetric( 325 + horizontal: 16, 326 + vertical: 4, 327 + ), 328 + ), 329 + ), 330 + ), 331 + Padding( 332 + padding: const EdgeInsets.symmetric(vertical: 8), 333 + child: Container( 334 + decoration: BoxDecoration( 335 + color: Theme.of( 336 + context, 314 337 ).colorScheme.error.withValues(alpha: 0.1), 315 338 borderRadius: BorderRadius.circular(12), 316 339 ),