Browse Source

project cleaning

Veloe 3 months ago
parent
commit
17c8b42f71

+ 77 - 0
lib/app_layout.dart

@@ -0,0 +1,77 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:veloe_kemono_party_flutter/models/nav_item.dart';
+
+class AppLayout extends ConsumerStatefulWidget {
+  final List<NavItem> navItems;
+  
+  const AppLayout({super.key, required this.navItems});
+
+  @override
+  ConsumerState<AppLayout> createState() => _AppLayoutState();
+}
+
+class _AppLayoutState extends ConsumerState<AppLayout> {
+  final _navIndex = StateProvider<int>((ref) => 0);
+
+  Widget _buildDesktopNavRail(int selectedIndex) {
+    return NavigationRail(
+      selectedIndex: selectedIndex,
+      onDestinationSelected: (index) => 
+          ref.read(_navIndex.notifier).state = index,
+      labelType: NavigationRailLabelType.all,
+      destinations: widget.navItems.map((item) => 
+          NavigationRailDestination(
+            icon: Icon(item.icon),
+            label: Text(item.label),
+          )).toList(),
+    );
+  }
+
+  Widget _buildMobileDrawer(int selectedIndex) {
+    return Drawer(
+      child: ListView(
+        children: [
+          const DrawerHeader(
+            decoration: BoxDecoration(color: Colors.blue),
+            child: Text('Navigation', style: TextStyle(color: Colors.white)),
+          ),
+          ...widget.navItems.asMap().entries.map((entry) => ListTile(
+            leading: Icon(entry.value.icon),
+            title: Text(entry.value.label),
+            selected: entry.key == selectedIndex,
+            onTap: () {
+              ref.read(_navIndex.notifier).state = entry.key;
+              Navigator.pop(context);
+            },
+          )),
+        ],
+      ),
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final selectedIndex = ref.watch(_navIndex);
+    final isDesktop = MediaQuery.of(context).size.width >= 600;
+
+    return Scaffold(
+      appBar: AppBar(
+        title: Text(widget.navItems[selectedIndex].label),
+        leading: isDesktop ? null : Builder(
+          builder: (context) => IconButton(
+            icon: const Icon(Icons.menu),
+            onPressed: () => Scaffold.of(context).openDrawer(),
+          ),
+        ),
+      ),
+      drawer: isDesktop ? null : _buildMobileDrawer(selectedIndex),
+      body: Row(
+        children: [
+          if (isDesktop) _buildDesktopNavRail(selectedIndex),
+          Expanded(child: widget.navItems[selectedIndex].page),
+        ],
+      ),
+    );
+  }
+}

+ 1 - 1
lib/kemono_client.dart

@@ -51,7 +51,7 @@ class KemonoClient {
       return (parsedData as List).map((x) => Post.fromJson(x)).toList();
     } on DioException catch (e) {
       throw Exception('Posts load failed: ${e.message}');
-    } on Exception catch (e) {
+    } on Exception {
         throw Exception('Oops something go wrong}');
     }
   }

+ 3 - 191
lib/main.dart

@@ -1,13 +1,13 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:flutter_cache_manager/flutter_cache_manager.dart';
+import 'package:veloe_kemono_party_flutter/app_layout.dart';
 import 'package:veloe_kemono_party_flutter/kemono_client.dart';
 import 'package:veloe_kemono_party_flutter/models/creator.dart';
+import 'package:veloe_kemono_party_flutter/models/nav_item.dart';
 import 'package:veloe_kemono_party_flutter/models/post.dart';
+import 'package:veloe_kemono_party_flutter/pages/home_screen.dart';
 import 'package:veloe_kemono_party_flutter/pages/posts_screen.dart';
-import 'package:veloe_kemono_party_flutter/pages/widgets/creator_card.dart';
-import 'package:veloe_kemono_party_flutter/pages/widgets/post_container.dart';
-
 import 'package:veloe_kemono_party_flutter/posts_notifier.dart';
 
 // Providers
@@ -48,194 +48,6 @@ final imageCacheManager = CacheManager(
     fileService: HttpFileService(),
   ),
 );
-// Navigation Items Model
-class NavItem {
-  final String label;
-  final IconData icon;
-  final Widget page;
-
-  const NavItem({
-    required this.label,
-    required this.icon,
-    required this.page,
-  });
-}
-
-// App Layout with Navigation
-class AppLayout extends ConsumerStatefulWidget {
-  final List<NavItem> navItems;
-  
-  const AppLayout({super.key, required this.navItems});
-
-  @override
-  ConsumerState<AppLayout> createState() => _AppLayoutState();
-}
-
-class _AppLayoutState extends ConsumerState<AppLayout> {
-  final _navIndex = StateProvider<int>((ref) => 0);
-
-  Widget _buildDesktopNavRail(int selectedIndex) {
-    return NavigationRail(
-      selectedIndex: selectedIndex,
-      onDestinationSelected: (index) => 
-          ref.read(_navIndex.notifier).state = index,
-      labelType: NavigationRailLabelType.all,
-      destinations: widget.navItems.map((item) => 
-          NavigationRailDestination(
-            icon: Icon(item.icon),
-            label: Text(item.label),
-          )).toList(),
-    );
-  }
-
-  Widget _buildMobileDrawer(int selectedIndex) {
-    return Drawer(
-      child: ListView(
-        children: [
-          const DrawerHeader(
-            decoration: BoxDecoration(color: Colors.blue),
-            child: Text('Navigation', style: TextStyle(color: Colors.white)),
-          ),
-          ...widget.navItems.asMap().entries.map((entry) => ListTile(
-            leading: Icon(entry.value.icon),
-            title: Text(entry.value.label),
-            selected: entry.key == selectedIndex,
-            onTap: () {
-              ref.read(_navIndex.notifier).state = entry.key;
-              Navigator.pop(context);
-            },
-          )),
-        ],
-      ),
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final selectedIndex = ref.watch(_navIndex);
-    final isDesktop = MediaQuery.of(context).size.width >= 600;
-
-    return Scaffold(
-      appBar: AppBar(
-        title: Text(widget.navItems[selectedIndex].label),
-        leading: isDesktop ? null : Builder(
-          builder: (context) => IconButton(
-            icon: const Icon(Icons.menu),
-            onPressed: () => Scaffold.of(context).openDrawer(),
-          ),
-        ),
-      ),
-      drawer: isDesktop ? null : _buildMobileDrawer(selectedIndex),
-      body: Row(
-        children: [
-          if (isDesktop) _buildDesktopNavRail(selectedIndex),
-          Expanded(child: widget.navItems[selectedIndex].page),
-        ],
-      ),
-    );
-  }
-}
-
-class HomeScreen extends ConsumerStatefulWidget {
-  const HomeScreen({super.key});
-
-  @override
-  ConsumerState<HomeScreen> createState() => _HomeScreenState();
-}
-
-class _HomeScreenState extends ConsumerState<HomeScreen> {
-  final TextEditingController _searchController = TextEditingController();
-  final _searchQuery = StateProvider<String>((ref) => ''); // Added search state
-
-  // Modified provider with search filtering
-  final filteredCreatorsProvider = FutureProvider.autoDispose.family<List<Creator>, String>(
-    (ref, query) async {
-      final originalList = await ref.watch(creatorsProvider.future);
-      return originalList.where(
-        (creator) => creator.name.toLowerCase().contains(query.toLowerCase())
-      ).toList();
-    },
-  );
-
-  @override
-  Widget build(BuildContext context) {
-    return DefaultTabController(
-      length: 2,
-      child: Scaffold(
-        appBar: AppBar(
-          title: _buildSearchField(), // Replaced title with search field
-          actions: [
-            IconButton(
-              icon: const Icon(Icons.refresh),
-              onPressed: () => ref.invalidate(filteredCreatorsProvider),
-            ),
-          ],
-        ),
-        body: _buildCreatorsList(ref.watch(
-              filteredCreatorsProvider(ref.watch(_searchQuery)) // Added query param
-        )),
-      ),
-    );
-  }
-
-  // New search field widget
-  Widget _buildSearchField() {
-    return TextField(
-      controller: _searchController,
-      decoration: InputDecoration(
-        hintText: 'Search creators...',
-        border: InputBorder.none,
-        suffixIcon: IconButton(
-          icon: const Icon(Icons.clear),
-          onPressed: () {
-            _searchController.clear();
-            ref.read(_searchQuery.notifier).state = '';
-          },
-        ),
-      ),
-      onChanged: (value) => ref.read(_searchQuery.notifier).state = value,
-    );
-  }
-
-  // Updated creators list with search
-  Widget _buildCreatorsList(AsyncValue<List<Creator>> creatorsAsync) {
-    return RefreshIndicator(
-      onRefresh: () => ref.refresh(filteredCreatorsProvider(ref.read(_searchQuery)).future),
-      child: creatorsAsync.when(
-        loading: () => const Center(child: CircularProgressIndicator()),
-        error: (error, _) => Center(child: Text(error.toString())),
-        data: (creators) => creators.isEmpty
-            ? const Center(child: Text('No matching creators found'))
-            : ListView.separated(
-                padding: const EdgeInsets.all(16),
-                itemCount: creators.length,
-                separatorBuilder: (_, __) => const SizedBox(height: 8),
-                itemBuilder: (context, index) => CreatorCard(creator: creators[index]),
-              ),
-      ),
-    );
-  }
-
-  Widget _buildGlobalPostsGrid() {
-    final postsAsync = ref.watch(postsProvider(('82522', 'patreon','')));
-
-    return postsAsync.when(
-      loading: () => const Center(child: CircularProgressIndicator()),
-      error: (error, _) => Center(child: Text(error.toString())),
-      data: (posts) => CustomScrollView(
-        slivers: [
-          SliverAppBar(),
-          SliverList(
-            delegate: SliverChildBuilderDelegate(
-              (context, index) => PostContainer(post: posts[index]),
-              childCount: posts.length,
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
 
 // Main Application
 void main() => runApp(

+ 13 - 0
lib/models/nav_item.dart

@@ -0,0 +1,13 @@
+import 'package:flutter/material.dart';
+
+class NavItem {
+  final String label;
+  final IconData icon;
+  final Widget page;
+
+  const NavItem({
+    required this.label,
+    required this.icon,
+    required this.page,
+  });
+}

+ 104 - 0
lib/pages/home_screen.dart

@@ -0,0 +1,104 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:veloe_kemono_party_flutter/main.dart';
+import 'package:veloe_kemono_party_flutter/models/creator.dart';
+import 'package:veloe_kemono_party_flutter/pages/widgets/creator_card.dart';
+
+class HomeScreen extends ConsumerStatefulWidget {
+  const HomeScreen({super.key});
+
+  @override
+  ConsumerState<HomeScreen> createState() => _HomeScreenState();
+}
+
+class _HomeScreenState extends ConsumerState<HomeScreen> {
+  final TextEditingController _searchController = TextEditingController();
+  final _searchQuery = StateProvider<String>((ref) => '');
+
+  final filteredCreatorsProvider = FutureProvider.autoDispose.family<List<Creator>, String>(
+    (ref, query) async {
+      final originalList = await ref.watch(creatorsProvider.future);
+      return originalList.where(
+        (creator) => creator.name.toLowerCase().contains(query.toLowerCase())
+      ).toList();
+    },
+  );
+
+  @override
+  Widget build(BuildContext context) {
+    return DefaultTabController(
+      length: 2,
+      child: Scaffold(
+        appBar: AppBar(
+          title: _buildSearchField(), 
+          actions: [
+            IconButton(
+              icon: const Icon(Icons.refresh),
+              onPressed: () => ref.invalidate(filteredCreatorsProvider),
+            ),
+          ],
+        ),
+        body: _buildCreatorsList(ref.watch(
+              filteredCreatorsProvider(ref.watch(_searchQuery))
+        )),
+      ),
+    );
+  }
+
+  Widget _buildSearchField() {
+    return TextField(
+      controller: _searchController,
+      decoration: InputDecoration(
+        hintText: 'Search creators...',
+        border: InputBorder.none,
+        suffixIcon: IconButton(
+          icon: const Icon(Icons.clear),
+          onPressed: () {
+            _searchController.clear();
+            ref.read(_searchQuery.notifier).state = '';
+          },
+        ),
+      ),
+      onChanged: (value) => ref.read(_searchQuery.notifier).state = value,
+    );
+  }
+
+  Widget _buildCreatorsList(AsyncValue<List<Creator>> creatorsAsync) {
+    return RefreshIndicator(
+      onRefresh: () => ref.refresh(filteredCreatorsProvider(ref.read(_searchQuery)).future),
+      child: creatorsAsync.when(
+        loading: () => const Center(child: CircularProgressIndicator()),
+        error: (error, _) => Center(child: Text(error.toString())),
+        data: (creators) => creators.isEmpty
+            ? const Center(child: Text('No matching creators found'))
+            : ListView.separated(
+                padding: const EdgeInsets.all(16),
+                itemCount: creators.length,
+                separatorBuilder: (_, __) => const SizedBox(height: 8),
+                itemBuilder: (context, index) => CreatorCard(creator: creators[index]),
+              ),
+      ),
+    );
+  }
+  /*
+  Widget _buildGlobalPostsGrid() {
+    final postsAsync = ref.watch(postsProvider(('82522', 'patreon','')));
+
+    return postsAsync.when(
+      loading: () => const Center(child: CircularProgressIndicator()),
+      error: (error, _) => Center(child: Text(error.toString())),
+      data: (posts) => CustomScrollView(
+        slivers: [
+          SliverAppBar(),
+          SliverList(
+            delegate: SliverChildBuilderDelegate(
+              (context, index) => PostContainer(post: posts[index]),
+              childCount: posts.length,
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+  */
+}

+ 0 - 1
lib/pages/widgets/creator_card.dart

@@ -30,7 +30,6 @@ class ResizedImage extends StatelessWidget {
   }
 }
 
-// UI Components
 class CreatorCard extends ConsumerWidget {
   final Creator creator;
   

+ 0 - 10
lib/pages/widgets/post_container.dart

@@ -20,13 +20,8 @@ class PostContainer extends StatelessWidget {
           mainAxisSize: MainAxisSize.min,
           crossAxisAlignment: CrossAxisAlignment.start,
           children: [
-            // Post Header
             _PostHeader(post: post),
-            
-            // Auto-sizing Content
             _PostContentSection(post: post),
-            
-            // Interactive Footer
             _PostActionsFooter(post: post),
           ],
         ),
@@ -35,7 +30,6 @@ class PostContainer extends StatelessWidget {
   }
 }
 
-// New header component
 class _PostHeader extends StatelessWidget {
   final Post post;
 
@@ -47,13 +41,11 @@ class _PostHeader extends StatelessWidget {
       padding: const EdgeInsets.only(bottom: 12),
       child: Row(
         children: [
-          // Author avatar
           /*CircleAvatar(
             backgroundImage: NetworkImage(post.author),
             radius: 20,
           ),*/
           const SizedBox(width: 12),
-          // Author info
           Expanded(
             child: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -129,7 +121,6 @@ void _sharePost(Post post) {
   //create link to share
 }
 
-// Modified content section with clickable links
 class _PostContentSection extends StatelessWidget {
   final Post post;
 
@@ -220,7 +211,6 @@ class _PostContentSection extends StatelessWidget {
   }
 }
 
-// URL handling method (add to parent class)
 Future<bool> _handleUrlLaunch(BuildContext context, String url) async {
   try {
       await launchUrl(

+ 1 - 5
lib/pages/widgets/post_detail_view.dart

@@ -83,15 +83,11 @@ class PostDetailView extends StatelessWidget {
     final uri = Uri.parse(url);
     final path = uri.path.toLowerCase();
     
-    // Handle URLs with query parameters or fragments
     final cleanPath = path.split('?').first.split('#').first;
-    
-    // Supported image extensions
     const imageExtensions = {
       'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg',
-      'tiff', 'heic', 'heif' // Added modern formats
+      'tiff', 'heic', 'heif' 
     };
-    
     return imageExtensions.any((ext) => cleanPath.endsWith('.$ext'));
   } catch (e) {
     return false; // Invalid URL format

+ 2 - 2
lib/posts_notifier.dart

@@ -5,7 +5,7 @@ import 'package:veloe_kemono_party_flutter/models/post.dart';
 class PostsNotifier extends StateNotifier<AsyncValue<List<Post>>> {
   final String creatorId;
   final String service;
-  final String query; // Add query parameter
+  final String query;
   final KemonoClient client;
   int _currentPage = 0;
 
@@ -26,7 +26,7 @@ class PostsNotifier extends StateNotifier<AsyncValue<List<Post>>> {
         creatorId, 
         service, 
         _currentPage * 50,
-        query // Pass query to client
+        query 
       );
       state = AsyncValue.data(posts);
       _currentPage = 1;