mobile bluesky app made with flutter lazurite.stormlightlabs.org/
mobile bluesky flutter
3
fork

Configure Feed

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

feat: update terms of service screen with Bluesky links

+41 -9
+1 -6
docs/TODO.md
··· 1 1 --- 2 2 title: To-Do/Parking Lot 3 - updated: 2026-04-14 3 + updated: 2026-04-26 4 4 --- 5 5 6 6 ## Tests ··· 59 59 --- 60 60 61 61 - Sidebar profile link should open account switcher, not go to profile. Long press to go to profile. 62 - 63 - ## Privacy Policy 64 - 65 - - Should mention that Lazurite is an AppView that doesn't store any user data. 66 - A link to BlueSky's privacy policy should be included. 67 62 68 63 ## Feature Completeness 69 64
+1 -2
lib/features/feed/presentation/post_thread_screen.dart
··· 870 870 final post = thread.post; 871 871 final record = Map<String, dynamic>.from(post.record); 872 872 873 - // TODO surface this action from timeline/search/saved cards once those entry points expose onMore. 874 - // TODO add edit affordance to additional owner-post contexts 873 + // Editing is currently exposed through the thread-screen overflow menu for owner posts. 875 874 final result = await context.push( 876 875 '/compose', 877 876 extra: ComposeRouteArgs(
+39 -1
lib/features/settings/presentation/terms_of_service_screen.dart
··· 9 9 static const _effectiveDate = 'April 15, 2026'; 10 10 static const _websiteUrl = 'https://stormlightlabs.org'; 11 11 static const _emailUrl = 'mailto:info@stormlightlabs.org'; 12 + static const _blueskyPrivacyUrl = 'https://bsky.social/about/support/privacy-policy'; 13 + static const _blueskyTermsUrl = 'https://bsky.social/about/support/tos'; 12 14 13 15 Future<void> _launch(String url) async { 14 16 await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication); ··· 72 74 'You may not misuse the app, break applicable law, or attempt unauthorized access to systems or accounts.', 73 75 ], 74 76 ), 75 - // TODO: do we link to BlueSky's legalese here? 77 + const _TermsSection( 78 + title: 'Bluesky terms and policies', 79 + paragraphs: [ 80 + 'Lazurite depends on Bluesky services, and your use of Bluesky is governed by Bluesky\'s own legal terms.', 81 + ], 82 + ), 83 + _PolicyLinks(onPrivacyTap: () => _launch(_blueskyPrivacyUrl), onTermsTap: () => _launch(_blueskyTermsUrl)), 76 84 const _TermsSection( 77 85 title: 'Your account and activity', 78 86 paragraphs: [ ··· 155 163 ); 156 164 } 157 165 } 166 + 167 + class _PolicyLinks extends StatelessWidget { 168 + const _PolicyLinks({required this.onPrivacyTap, required this.onTermsTap}); 169 + 170 + final VoidCallback onPrivacyTap; 171 + final VoidCallback onTermsTap; 172 + 173 + @override 174 + Widget build(BuildContext context) { 175 + return Padding( 176 + padding: const EdgeInsets.only(bottom: 18), 177 + child: Wrap( 178 + spacing: 8, 179 + runSpacing: 8, 180 + children: [ 181 + OutlinedButton.icon( 182 + onPressed: onPrivacyTap, 183 + icon: const Icon(Icons.privacy_tip_outlined), 184 + label: const Text('Bluesky Privacy Policy'), 185 + ), 186 + OutlinedButton.icon( 187 + onPressed: onTermsTap, 188 + icon: const Icon(Icons.description_outlined), 189 + label: const Text('Bluesky Terms of Service'), 190 + ), 191 + ], 192 + ), 193 + ); 194 + } 195 + }