mirror of
https://gitlab.com/mysocialportal/relatica
synced 2024-10-18 13:33:32 +00:00
Add button bar w/nav to home, notifications, and profile
This commit is contained in:
parent
37857a96d6
commit
6af1c4f214
9 changed files with 225 additions and 13 deletions
126
lib/controls/app_bottom_nav_bar.dart
Normal file
126
lib/controls/app_bottom_nav_bar.dart
Normal file
|
@ -0,0 +1,126 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../routes.dart';
|
||||
|
||||
enum NavBarButtons {
|
||||
home,
|
||||
notifications,
|
||||
messages,
|
||||
contacts,
|
||||
profile,
|
||||
}
|
||||
|
||||
class AppBottomNavBar extends StatelessWidget {
|
||||
final NavBarButtons currentButton;
|
||||
|
||||
const AppBottomNavBar({super.key, required this.currentButton});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BottomNavigationBar(
|
||||
onTap: (index) {
|
||||
final newButton = _indexToButton(index);
|
||||
if (newButton == currentButton) {
|
||||
print('same button do nothing');
|
||||
return;
|
||||
}
|
||||
|
||||
switch (newButton) {
|
||||
case NavBarButtons.home:
|
||||
Navigator.of(context).popUntil((route) {
|
||||
return route.settings.name == ScreenPaths.home;
|
||||
});
|
||||
break;
|
||||
case NavBarButtons.notifications:
|
||||
context.pushNamed(ScreenPaths.notifications);
|
||||
break;
|
||||
case NavBarButtons.messages:
|
||||
// TODO: Handle this case.
|
||||
break;
|
||||
case NavBarButtons.contacts:
|
||||
// TODO: Handle this case.
|
||||
break;
|
||||
case NavBarButtons.profile:
|
||||
context.pushNamed(ScreenPaths.profile);
|
||||
break;
|
||||
}
|
||||
},
|
||||
type: BottomNavigationBarType.fixed,
|
||||
selectedItemColor: Colors.black,
|
||||
unselectedItemColor: Colors.black54,
|
||||
currentIndex: _buttonToIndex(currentButton),
|
||||
items: _menuItems,
|
||||
);
|
||||
}
|
||||
|
||||
int _buttonToIndex(NavBarButtons button) {
|
||||
switch (button) {
|
||||
case NavBarButtons.home:
|
||||
return 0;
|
||||
case NavBarButtons.notifications:
|
||||
return 1;
|
||||
case NavBarButtons.messages:
|
||||
return 2;
|
||||
case NavBarButtons.contacts:
|
||||
return 3;
|
||||
case NavBarButtons.profile:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
NavBarButtons _indexToButton(int index) {
|
||||
if (index == 0) {
|
||||
return NavBarButtons.home;
|
||||
}
|
||||
|
||||
if (index == 1) {
|
||||
return NavBarButtons.notifications;
|
||||
}
|
||||
|
||||
if (index == 2) {
|
||||
return NavBarButtons.messages;
|
||||
}
|
||||
|
||||
if (index == 3) {
|
||||
return NavBarButtons.contacts;
|
||||
}
|
||||
|
||||
if (index == 4) {
|
||||
return NavBarButtons.profile;
|
||||
}
|
||||
|
||||
throw ArgumentError('$index has no button type');
|
||||
}
|
||||
|
||||
List<BottomNavigationBarItem> get _menuItems {
|
||||
return const [
|
||||
BottomNavigationBarItem(
|
||||
label: 'Home',
|
||||
icon: Icon(Icons.home_outlined),
|
||||
activeIcon: Icon(Icons.home_filled),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: 'Notifications',
|
||||
icon: Icon(Icons.notifications_none_outlined),
|
||||
activeIcon: Icon(Icons.notifications),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: 'Messages',
|
||||
icon: Icon(Icons.messenger_outline),
|
||||
activeIcon: Icon(Icons.messenger),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: 'Contacts',
|
||||
icon: Icon(Icons.people_outline),
|
||||
activeIcon: Icon(Icons.people_sharp),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: 'Profile',
|
||||
icon: Icon(Icons.person_outline),
|
||||
activeIcon: Icon(Icons.person),
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
|
@ -91,6 +91,9 @@ class _StatusControlState extends State<StatusControl> {
|
|||
ElapsedDateUtils.epochSecondsToString(entry.backdatedTimestamp),
|
||||
style: Theme.of(context).textTheme.caption,
|
||||
),
|
||||
Text(
|
||||
item.id,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
@ -46,7 +46,7 @@ class FriendicaClient {
|
|||
FutureResult<List<TimelineEntry>, ExecError> getTimeline(
|
||||
{required TimelineIdentifiers type,
|
||||
int sinceId = 0,
|
||||
int limit = 100}) async {
|
||||
int limit = 20}) async {
|
||||
final String timelinePath = _typeToTimelinePath(type);
|
||||
final String timelineQPs = _typeToTimelineQueryParameters(type);
|
||||
final baseUrl = 'https://$serverName/api/v1/timelines/$timelinePath';
|
||||
|
@ -154,7 +154,7 @@ class FriendicaClient {
|
|||
type: ErrorType.authentication,
|
||||
message: '${response.statusCode}: ${response.reasonPhrase}'));
|
||||
}
|
||||
return Result.ok(response.body);
|
||||
return Result.ok(utf8.decode(response.bodyBytes));
|
||||
} catch (e) {
|
||||
return Result.error(
|
||||
ExecError(type: ErrorType.localError, message: e.toString()));
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'package:result_monad/result_monad.dart';
|
|||
import 'globals.dart';
|
||||
import 'models/TimelineIdentifiers.dart';
|
||||
import 'routes.dart';
|
||||
import 'screens/sign_in.dart';
|
||||
import 'services/auth_service.dart';
|
||||
import 'services/connections_manager.dart';
|
||||
import 'services/entry_manager_service.dart';
|
||||
|
@ -86,12 +85,3 @@ class App extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Home extends StatelessWidget {
|
||||
const Home({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SignInScreen();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ import 'package:go_router/go_router.dart';
|
|||
import 'globals.dart';
|
||||
import 'screens/editor.dart';
|
||||
import 'screens/home.dart';
|
||||
import 'screens/notifications_screen.dart';
|
||||
import 'screens/profile_screen.dart';
|
||||
import 'screens/sign_in.dart';
|
||||
import 'screens/splash.dart';
|
||||
import 'services/auth_service.dart';
|
||||
|
@ -10,6 +12,8 @@ import 'services/auth_service.dart';
|
|||
class ScreenPaths {
|
||||
static String splash = '/splash';
|
||||
static String home = '/';
|
||||
static String profile = '/profile';
|
||||
static String notifications = '/notifications';
|
||||
static String signin = '/signin';
|
||||
static String signup = '/signup';
|
||||
static String settings = '/settings';
|
||||
|
@ -52,7 +56,24 @@ final appRouter = GoRouter(
|
|||
GoRoute(
|
||||
path: ScreenPaths.home,
|
||||
name: ScreenPaths.home,
|
||||
builder: (context, state) => HomeScreen(),
|
||||
pageBuilder: (context, state) => NoTransitionPage(
|
||||
name: ScreenPaths.home,
|
||||
child: HomeScreen(),
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: ScreenPaths.profile,
|
||||
name: ScreenPaths.profile,
|
||||
pageBuilder: (context, state) => NoTransitionPage(
|
||||
child: ProfileScreen(),
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: ScreenPaths.notifications,
|
||||
name: ScreenPaths.notifications,
|
||||
pageBuilder: (context, state) => NoTransitionPage(
|
||||
child: NotificationsScreen(),
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: ScreenPaths.splash,
|
||||
|
|
|
@ -3,11 +3,14 @@ import 'package:go_router/go_router.dart';
|
|||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../controls/app_bottom_nav_bar.dart';
|
||||
import '../controls/timeline/status_control.dart';
|
||||
import '../models/TimelineIdentifiers.dart';
|
||||
import '../services/timeline_manager.dart';
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
const HomeScreen({super.key});
|
||||
|
||||
@override
|
||||
State<HomeScreen> createState() => _HomeScreenState();
|
||||
}
|
||||
|
@ -57,6 +60,9 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||
Expanded(child: buildTimelineComponent(context, tm))
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: AppBottomNavBar(
|
||||
currentButton: NavBarButtons.home,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
27
lib/screens/notifications_screen.dart
Normal file
27
lib/screens/notifications_screen.dart
Normal file
|
@ -0,0 +1,27 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../controls/app_bottom_nav_bar.dart';
|
||||
|
||||
class NotificationsScreen extends StatelessWidget {
|
||||
const NotificationsScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Notifications'),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Notifications'),
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: AppBottomNavBar(
|
||||
currentButton: NavBarButtons.notifications,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
38
lib/screens/profile_screen.dart
Normal file
38
lib/screens/profile_screen.dart
Normal file
|
@ -0,0 +1,38 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../controls/app_bottom_nav_bar.dart';
|
||||
import '../controls/padding.dart';
|
||||
import '../services/auth_service.dart';
|
||||
|
||||
class ProfileScreen extends StatelessWidget {
|
||||
const ProfileScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final authService = context.watch<AuthService>();
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Profile'),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Profile: ${authService.currentClient.fold(onSuccess: (client) => client.credentials.handle, onError: (error) => 'Error Getting Profile')}'),
|
||||
VerticalPadding(),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
await authService.signOut();
|
||||
},
|
||||
child: Text('Sign Out')),
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: AppBottomNavBar(
|
||||
currentButton: NavBarButtons.profile,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -50,6 +50,7 @@ class SecretsService {
|
|||
_secureStorage.write(key: _usernameKey, value: credentials.username);
|
||||
_secureStorage.write(key: _passwordKey, value: credentials.password);
|
||||
_secureStorage.write(key: _serverNameKey, value: credentials.serverName);
|
||||
_cachedCredentials = credentials;
|
||||
return Result.ok(credentials);
|
||||
} on PlatformException catch (e) {
|
||||
return Result.error(ExecError(
|
||||
|
|
Loading…
Reference in a new issue