kopia lustrzana https://gitlab.com/mysocialportal/relatica
Add button bar w/nav to home, notifications, and profile
rodzic
37857a96d6
commit
6af1c4f214
|
@ -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),
|
ElapsedDateUtils.epochSecondsToString(entry.backdatedTimestamp),
|
||||||
style: Theme.of(context).textTheme.caption,
|
style: Theme.of(context).textTheme.caption,
|
||||||
),
|
),
|
||||||
|
Text(
|
||||||
|
item.id,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -46,7 +46,7 @@ class FriendicaClient {
|
||||||
FutureResult<List<TimelineEntry>, ExecError> getTimeline(
|
FutureResult<List<TimelineEntry>, ExecError> getTimeline(
|
||||||
{required TimelineIdentifiers type,
|
{required TimelineIdentifiers type,
|
||||||
int sinceId = 0,
|
int sinceId = 0,
|
||||||
int limit = 100}) async {
|
int limit = 20}) async {
|
||||||
final String timelinePath = _typeToTimelinePath(type);
|
final String timelinePath = _typeToTimelinePath(type);
|
||||||
final String timelineQPs = _typeToTimelineQueryParameters(type);
|
final String timelineQPs = _typeToTimelineQueryParameters(type);
|
||||||
final baseUrl = 'https://$serverName/api/v1/timelines/$timelinePath';
|
final baseUrl = 'https://$serverName/api/v1/timelines/$timelinePath';
|
||||||
|
@ -154,7 +154,7 @@ class FriendicaClient {
|
||||||
type: ErrorType.authentication,
|
type: ErrorType.authentication,
|
||||||
message: '${response.statusCode}: ${response.reasonPhrase}'));
|
message: '${response.statusCode}: ${response.reasonPhrase}'));
|
||||||
}
|
}
|
||||||
return Result.ok(response.body);
|
return Result.ok(utf8.decode(response.bodyBytes));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Result.error(
|
return Result.error(
|
||||||
ExecError(type: ErrorType.localError, message: e.toString()));
|
ExecError(type: ErrorType.localError, message: e.toString()));
|
||||||
|
|
|
@ -6,7 +6,6 @@ import 'package:result_monad/result_monad.dart';
|
||||||
import 'globals.dart';
|
import 'globals.dart';
|
||||||
import 'models/TimelineIdentifiers.dart';
|
import 'models/TimelineIdentifiers.dart';
|
||||||
import 'routes.dart';
|
import 'routes.dart';
|
||||||
import 'screens/sign_in.dart';
|
|
||||||
import 'services/auth_service.dart';
|
import 'services/auth_service.dart';
|
||||||
import 'services/connections_manager.dart';
|
import 'services/connections_manager.dart';
|
||||||
import 'services/entry_manager_service.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 'globals.dart';
|
||||||
import 'screens/editor.dart';
|
import 'screens/editor.dart';
|
||||||
import 'screens/home.dart';
|
import 'screens/home.dart';
|
||||||
|
import 'screens/notifications_screen.dart';
|
||||||
|
import 'screens/profile_screen.dart';
|
||||||
import 'screens/sign_in.dart';
|
import 'screens/sign_in.dart';
|
||||||
import 'screens/splash.dart';
|
import 'screens/splash.dart';
|
||||||
import 'services/auth_service.dart';
|
import 'services/auth_service.dart';
|
||||||
|
@ -10,6 +12,8 @@ import 'services/auth_service.dart';
|
||||||
class ScreenPaths {
|
class ScreenPaths {
|
||||||
static String splash = '/splash';
|
static String splash = '/splash';
|
||||||
static String home = '/';
|
static String home = '/';
|
||||||
|
static String profile = '/profile';
|
||||||
|
static String notifications = '/notifications';
|
||||||
static String signin = '/signin';
|
static String signin = '/signin';
|
||||||
static String signup = '/signup';
|
static String signup = '/signup';
|
||||||
static String settings = '/settings';
|
static String settings = '/settings';
|
||||||
|
@ -52,7 +56,24 @@ final appRouter = GoRouter(
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: ScreenPaths.home,
|
path: ScreenPaths.home,
|
||||||
name: 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(
|
GoRoute(
|
||||||
path: ScreenPaths.splash,
|
path: ScreenPaths.splash,
|
||||||
|
|
|
@ -3,11 +3,14 @@ import 'package:go_router/go_router.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../controls/app_bottom_nav_bar.dart';
|
||||||
import '../controls/timeline/status_control.dart';
|
import '../controls/timeline/status_control.dart';
|
||||||
import '../models/TimelineIdentifiers.dart';
|
import '../models/TimelineIdentifiers.dart';
|
||||||
import '../services/timeline_manager.dart';
|
import '../services/timeline_manager.dart';
|
||||||
|
|
||||||
class HomeScreen extends StatefulWidget {
|
class HomeScreen extends StatefulWidget {
|
||||||
|
const HomeScreen({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<HomeScreen> createState() => _HomeScreenState();
|
State<HomeScreen> createState() => _HomeScreenState();
|
||||||
}
|
}
|
||||||
|
@ -57,6 +60,9 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
Expanded(child: buildTimelineComponent(context, tm))
|
Expanded(child: buildTimelineComponent(context, tm))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
bottomNavigationBar: AppBottomNavBar(
|
||||||
|
currentButton: NavBarButtons.home,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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: _usernameKey, value: credentials.username);
|
||||||
_secureStorage.write(key: _passwordKey, value: credentials.password);
|
_secureStorage.write(key: _passwordKey, value: credentials.password);
|
||||||
_secureStorage.write(key: _serverNameKey, value: credentials.serverName);
|
_secureStorage.write(key: _serverNameKey, value: credentials.serverName);
|
||||||
|
_cachedCredentials = credentials;
|
||||||
return Result.ok(credentials);
|
return Result.ok(credentials);
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return Result.error(ExecError(
|
return Result.error(ExecError(
|
||||||
|
|
Ładowanie…
Reference in New Issue