Skip to content
This repository was archived by the owner on Jul 31, 2025. It is now read-only.

Commit c468dad

Browse files
committed
refactoring
1 parent b2868d9 commit c468dad

16 files changed

Lines changed: 512 additions & 626 deletions

.vscode/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"IDX.aI.enableInlineCompletion": true,
3+
"IDX.aI.enableCodebaseIndexing": true
4+
}

lib/main.dart

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ import 'package:provider/provider.dart';
33
import 'package:vpn_client/pages/apps/apps_page.dart';
44
import 'package:vpn_client/pages/main/main_page.dart';
55
import 'package:vpn_client/pages/servers/servers_page.dart';
6+
import 'package:vpn_client/pages/settings/settings_page.dart';
7+
import 'package:vpn_client/pages/speed/speed_page.dart';
8+
import 'package:vpn_client/providers/vpn_provider.dart';
69
import 'package:vpn_client/theme_provider.dart';
710

811
import 'design/colors.dart';
912
import 'nav_bar.dart';
1013

1114
void main() {
12-
runApp(
13-
ChangeNotifierProvider(create: (_) => ThemeProvider(), child: const App()),
14-
);
15+
runApp(MultiProvider(providers: [ChangeNotifierProvider(create: (_) => ThemeProvider()), ChangeNotifierProvider(create: (_) => VPNProvider())], child: const App()));
1516
}
1617

1718
class App extends StatelessWidget {
@@ -50,8 +51,8 @@ class _MainScreenState extends State<MainScreen> {
5051
const AppsPage(),
5152
ServersPage(onNavBarTap: _handleNavBarTap),
5253
const MainPage(),
53-
const PlaceholderPage(text: 'Speed Page'),
54-
const PlaceholderPage(text: 'Settings Page'),
54+
const SpeedPage(),
55+
const SettingsPage(),
5556
];
5657
}
5758

@@ -68,17 +69,8 @@ class _MainScreenState extends State<MainScreen> {
6869
bottomNavigationBar: NavBar(
6970
initialIndex: _currentIndex,
7071
onItemTapped: _handleNavBarTap,
72+
selectedColor: Theme.of(context).colorScheme.primary,
7173
),
7274
);
7375
}
7476
}
75-
76-
class PlaceholderPage extends StatelessWidget {
77-
final String text;
78-
const PlaceholderPage({super.key, required this.text});
79-
80-
@override
81-
Widget build(BuildContext context) {
82-
return Center(child: Text(text));
83-
}
84-
}

lib/models/nav_item.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import 'package:flutter/material.dart';
2+
3+
class NavItem {
4+
final Widget inactiveIcon;
5+
final Widget activeIcon;
6+
7+
NavItem({required this.inactiveIcon, required this.activeIcon});
8+
}

lib/nav_bar.dart

Lines changed: 32 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,55 @@
11
import 'package:flutter/material.dart';
22
import 'design/images.dart';
3+
import 'package:vpn_client/models/nav_item.dart';
34

4-
class NavBar extends StatefulWidget {
5+
class NavBar extends StatelessWidget {
56
final int initialIndex;
67
final Function(int) onItemTapped;
8+
final Color selectedColor;
79

8-
const NavBar({super.key, this.initialIndex = 2, required this.onItemTapped});
9-
10-
@override
11-
State<NavBar> createState() => NavBarState();
12-
}
13-
14-
class NavBarState extends State<NavBar> {
15-
late int _selectedIndex;
16-
17-
final List<Widget> _inactiveIcons = [
18-
appIcon,
19-
serverIcon,
20-
homeIcon,
21-
speedIcon,
22-
settingsIcon,
23-
];
24-
25-
final List<Widget> _activeIcons = [
26-
activeAppIcon,
27-
activeServerIcon,
28-
activeHomeIcon,
29-
speedIcon,
30-
settingsIcon,
31-
];
32-
33-
@override
34-
void initState() {
35-
super.initState();
36-
_selectedIndex = widget.initialIndex;
37-
}
38-
39-
void _onItemTapped(int index) {
40-
setState(() {
41-
_selectedIndex = index;
42-
});
43-
widget.onItemTapped(index);
44-
}
10+
const NavBar({
11+
super.key,
12+
this.initialIndex = 2,
13+
required this.onItemTapped,
14+
required this.selectedColor,
15+
});
4516

4617
@override
4718
Widget build(BuildContext context) {
19+
final List<NavItem> navItems = [
20+
NavItem(inactiveIcon: appIcon, activeIcon: activeAppIcon),
21+
NavItem(inactiveIcon: serverIcon, activeIcon: activeServerIcon),
22+
NavItem(inactiveIcon: homeIcon, activeIcon: activeHomeIcon),
23+
NavItem(inactiveIcon: speedIcon, activeIcon: speedIcon),
24+
NavItem(inactiveIcon: settingsIcon, activeIcon: settingsIcon),
25+
];
26+
4827
return Container(
4928
alignment: Alignment.center,
5029
width: MediaQuery.of(context).size.width,
5130
height: 60,
5231
margin: const EdgeInsets.only(bottom: 30),
5332
padding: const EdgeInsets.symmetric(horizontal: 30),
54-
decoration: BoxDecoration(color: Theme.of(context).colorScheme.surface),
33+
decoration:
34+
BoxDecoration(color: Theme.of(context).colorScheme.surface),
5535
child: Row(
56-
children: List.generate(_inactiveIcons.length, (index) {
57-
bool isActive = _selectedIndex == index;
36+
mainAxisAlignment: MainAxisAlignment.spaceAround,
37+
children: List.generate(navItems.length, (index) {
38+
bool isActive = initialIndex == index;
5839
return GestureDetector(
59-
onTap: () => _onItemTapped(index),
60-
child: SizedBox(
61-
width: (MediaQuery.of(context).size.width-60)/5,
62-
child: AnimatedContainer(
40+
onTap: () => onItemTapped(index),
41+
child: AnimatedContainer(
6342
duration: const Duration(milliseconds: 200),
6443
curve: Curves.easeInOut,
6544
padding: const EdgeInsets.all(8),
66-
child: isActive ? _activeIcons[index] : _inactiveIcons[index],
67-
),)
45+
child: isActive
46+
? ColorFiltered(
47+
colorFilter: ColorFilter.mode(
48+
selectedColor, BlendMode.srcIn),
49+
child: navItems[index].activeIcon,
50+
)
51+
: navItems[index].inactiveIcon,
52+
),
6853
);
6954
}),
7055
),

lib/pages/main/location_widget.dart

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,67 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_svg/svg.dart';
33

4+
45
class LocationWidget extends StatelessWidget {
6+
final String title;
57
final Map<String, dynamic>? selectedServer;
8+
final VoidCallback? onTap;
69

7-
const LocationWidget({super.key, this.selectedServer});
10+
const LocationWidget({
11+
super.key,
12+
required this.title,
13+
this.selectedServer,
14+
this.onTap,
15+
});
816

917
@override
1018
Widget build(BuildContext context) {
11-
final String locationName = selectedServer?['text'] ?? '...';
12-
final String iconPath =
13-
selectedServer?['icon'] ?? 'assets/images/flags/auto.svg';
19+
final String locationName = selectedServer?['text'] ?? '...'; final String iconPath = selectedServer?['icon'] ?? 'assets/images/flags/auto.svg';
1420

15-
return Container(
16-
margin: const EdgeInsets.all(30),
17-
padding: const EdgeInsets.only(left: 14),
21+
return GestureDetector( onTap: onTap,
22+
child: Container(
23+
padding: const EdgeInsets.only(left: 14),
24+
decoration: BoxDecoration(
25+
color: Theme.of(context).colorScheme.onSurface,
26+
borderRadius: BorderRadius.circular(12),
27+
),
28+
child: Row(
29+
children: [
30+
Column(
31+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
32+
crossAxisAlignment: CrossAxisAlignment.start,
33+
children: [
34+
Text(
35+
title,
36+
style: TextStyle(
37+
fontSize: 14,
38+
fontWeight: FontWeight.w400,
39+
color: Theme.of(context).colorScheme.secondary,
40+
),
41+
),
42+
Text(
43+
locationName,
44+
style: TextStyle(
45+
fontSize: 17,
46+
fontWeight: FontWeight.w400,
47+
color: Theme.of(context).colorScheme.primary,
48+
),
49+
),
50+
],
51+
),
52+
const Spacer(),
53+
Column(
54+
children: [
55+
const SizedBox(height: 20),
56+
SvgPicture.asset(iconPath, width: 48, height: 48),
57+
],
58+
),
59+
],
60+
),
61+
),
62+
);
63+
}
64+
}
1865
decoration: BoxDecoration(
1966
color: Theme.of(context).colorScheme.onSurface,
2067
borderRadius: BorderRadius.circular(12),

0 commit comments

Comments
 (0)