kopia lustrzana https://gitlab.com/mysocialportal/relatica
Merge branch 'settings-and-dark-mode' into 'main'
Settings and dark mode See merge request mysocialportal/friendica_portal!6codemagic-setup
commit
6e9d34ff54
|
@ -0,0 +1,11 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AppTheme {
|
||||||
|
static ThemeData light = ThemeData(primarySwatch: Colors.indigo);
|
||||||
|
|
||||||
|
static ThemeData dark = ThemeData.from(
|
||||||
|
colorScheme: ColorScheme.fromSwatch(
|
||||||
|
primarySwatch: Colors.cyan,
|
||||||
|
brightness: Brightness.dark,
|
||||||
|
));
|
||||||
|
}
|
|
@ -9,10 +9,8 @@ import '../services/notifications_manager.dart';
|
||||||
enum NavBarButtons {
|
enum NavBarButtons {
|
||||||
timelines,
|
timelines,
|
||||||
notifications,
|
notifications,
|
||||||
messages,
|
|
||||||
gallery,
|
|
||||||
contacts,
|
contacts,
|
||||||
profile,
|
menu,
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppBottomNavBar extends StatelessWidget {
|
class AppBottomNavBar extends StatelessWidget {
|
||||||
|
@ -41,25 +39,17 @@ class AppBottomNavBar extends StatelessWidget {
|
||||||
case NavBarButtons.notifications:
|
case NavBarButtons.notifications:
|
||||||
context.pushNamed(ScreenPaths.notifications);
|
context.pushNamed(ScreenPaths.notifications);
|
||||||
break;
|
break;
|
||||||
case NavBarButtons.messages:
|
|
||||||
// TODO: Handle this case.
|
|
||||||
break;
|
|
||||||
case NavBarButtons.contacts:
|
case NavBarButtons.contacts:
|
||||||
context.pushNamed(ScreenPaths.contacts);
|
context.pushNamed(ScreenPaths.contacts);
|
||||||
break;
|
break;
|
||||||
case NavBarButtons.profile:
|
case NavBarButtons.menu:
|
||||||
context.pushNamed(ScreenPaths.profile);
|
context.pushNamed(ScreenPaths.menu);
|
||||||
break;
|
|
||||||
case NavBarButtons.gallery:
|
|
||||||
context.pushNamed(ScreenPaths.gallery);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
selectedItemColor: Colors.black,
|
|
||||||
unselectedItemColor: Colors.black54,
|
|
||||||
currentIndex: _buttonToIndex(currentButton),
|
currentIndex: _buttonToIndex(currentButton),
|
||||||
items: _menuItems(hasNotifications),
|
items: _menuItems(context, hasNotifications),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,14 +59,10 @@ class AppBottomNavBar extends StatelessWidget {
|
||||||
return 0;
|
return 0;
|
||||||
case NavBarButtons.notifications:
|
case NavBarButtons.notifications:
|
||||||
return 1;
|
return 1;
|
||||||
case NavBarButtons.gallery:
|
|
||||||
return 2;
|
|
||||||
case NavBarButtons.messages:
|
|
||||||
return 3;
|
|
||||||
case NavBarButtons.contacts:
|
case NavBarButtons.contacts:
|
||||||
return 4;
|
return 2;
|
||||||
case NavBarButtons.profile:
|
case NavBarButtons.menu:
|
||||||
return 5;
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,25 +76,18 @@ class AppBottomNavBar extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 2) {
|
if (index == 2) {
|
||||||
return NavBarButtons.gallery;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == 3) {
|
|
||||||
return NavBarButtons.messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == 4) {
|
|
||||||
return NavBarButtons.contacts;
|
return NavBarButtons.contacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 5) {
|
if (index == 3) {
|
||||||
return NavBarButtons.profile;
|
return NavBarButtons.menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw ArgumentError('$index has no button type');
|
throw ArgumentError('$index has no button type');
|
||||||
}
|
}
|
||||||
|
|
||||||
List<BottomNavigationBarItem> _menuItems(bool hasNotifications) {
|
List<BottomNavigationBarItem> _menuItems(
|
||||||
|
BuildContext context, bool hasNotifications) {
|
||||||
return [
|
return [
|
||||||
const BottomNavigationBarItem(
|
const BottomNavigationBarItem(
|
||||||
label: 'Timelines',
|
label: 'Timelines',
|
||||||
|
@ -124,25 +103,15 @@ class AppBottomNavBar extends StatelessWidget {
|
||||||
? Icons.notifications_active
|
? Icons.notifications_active
|
||||||
: Icons.notifications),
|
: Icons.notifications),
|
||||||
),
|
),
|
||||||
const BottomNavigationBarItem(
|
|
||||||
label: 'Gallery',
|
|
||||||
icon: Icon(Icons.photo_library_outlined),
|
|
||||||
activeIcon: Icon(Icons.photo_library),
|
|
||||||
),
|
|
||||||
const BottomNavigationBarItem(
|
|
||||||
label: 'Messages',
|
|
||||||
icon: Icon(Icons.messenger_outline),
|
|
||||||
activeIcon: Icon(Icons.messenger),
|
|
||||||
),
|
|
||||||
const BottomNavigationBarItem(
|
const BottomNavigationBarItem(
|
||||||
label: 'Contacts',
|
label: 'Contacts',
|
||||||
icon: Icon(Icons.people_outline),
|
icon: Icon(Icons.people_outline),
|
||||||
activeIcon: Icon(Icons.people_sharp),
|
activeIcon: Icon(Icons.people_sharp),
|
||||||
),
|
),
|
||||||
const BottomNavigationBarItem(
|
const BottomNavigationBarItem(
|
||||||
label: 'Profile',
|
label: 'Menu',
|
||||||
icon: Icon(Icons.person_outline),
|
icon: Icon(Icons.menu),
|
||||||
activeIcon: Icon(Icons.person),
|
activeIcon: Icon(Icons.menu_open),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../routes.dart';
|
||||||
|
|
||||||
|
class StandardAppBar {
|
||||||
|
static AppBar build(BuildContext context, String title) {
|
||||||
|
return AppBar(
|
||||||
|
title: Text(title),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).popUntil((route) {
|
||||||
|
return route.settings.name == ScreenPaths.timelines;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.home),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:result_monad/result_monad.dart';
|
||||||
|
|
||||||
|
import 'data/interfaces/connections_repo_intf.dart';
|
||||||
|
import 'data/interfaces/groups_repo.intf.dart';
|
||||||
|
import 'data/interfaces/hashtag_repo_intf.dart';
|
||||||
|
import 'data/memory/memory_groups_repo.dart';
|
||||||
|
import 'data/objectbox/objectbox_cache.dart';
|
||||||
|
import 'data/objectbox/objectbox_connections_repo.dart';
|
||||||
|
import 'data/objectbox/objectbox_hashtag_repo.dart';
|
||||||
|
import 'globals.dart';
|
||||||
|
import 'models/TimelineIdentifiers.dart';
|
||||||
|
import 'services/auth_service.dart';
|
||||||
|
import 'services/connections_manager.dart';
|
||||||
|
import 'services/entry_manager_service.dart';
|
||||||
|
import 'services/gallery_service.dart';
|
||||||
|
import 'services/hashtag_service.dart';
|
||||||
|
import 'services/media_upload_attachment_helper.dart';
|
||||||
|
import 'services/notifications_manager.dart';
|
||||||
|
import 'services/secrets_service.dart';
|
||||||
|
import 'services/setting_service.dart';
|
||||||
|
import 'services/timeline_manager.dart';
|
||||||
|
|
||||||
|
final _logger = Logger('DI_Init');
|
||||||
|
|
||||||
|
Future<void> dependencyInjectionInitialization() async {
|
||||||
|
final authService = AuthService();
|
||||||
|
final secretsService = SecretsService();
|
||||||
|
final entryManagerService = EntryManagerService();
|
||||||
|
final timelineManager = TimelineManager();
|
||||||
|
final galleryService = GalleryService();
|
||||||
|
|
||||||
|
getIt.registerSingletonAsync(() async {
|
||||||
|
final service = SettingsService();
|
||||||
|
await service.initialize();
|
||||||
|
return service;
|
||||||
|
});
|
||||||
|
|
||||||
|
final objectBoxCache = await ObjectBoxCache.create();
|
||||||
|
getIt.registerSingleton<ObjectBoxCache>(objectBoxCache);
|
||||||
|
getIt.registerSingleton<IConnectionsRepo>(ObjectBoxConnectionsRepo());
|
||||||
|
getIt.registerSingleton<IHashtagRepo>(ObjectBoxHashtagRepo());
|
||||||
|
getIt.registerSingleton<IGroupsRepo>(MemoryGroupsRepo());
|
||||||
|
getIt.registerLazySingleton<ConnectionsManager>(() => ConnectionsManager());
|
||||||
|
getIt.registerLazySingleton<HashtagService>(() => HashtagService());
|
||||||
|
getIt.registerSingleton(galleryService);
|
||||||
|
getIt.registerSingleton<EntryManagerService>(entryManagerService);
|
||||||
|
getIt.registerSingleton<SecretsService>(secretsService);
|
||||||
|
getIt.registerSingleton<AuthService>(authService);
|
||||||
|
getIt.registerSingleton<TimelineManager>(timelineManager);
|
||||||
|
getIt.registerLazySingleton<MediaUploadAttachmentHelper>(
|
||||||
|
() => MediaUploadAttachmentHelper());
|
||||||
|
getIt.registerLazySingleton<NotificationsManager>(
|
||||||
|
() => NotificationsManager());
|
||||||
|
galleryService.getGalleries();
|
||||||
|
|
||||||
|
await secretsService.initialize().andThenSuccessAsync((credentials) async {
|
||||||
|
if (credentials.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final wasLoggedIn = await authService.getStoredLoginState();
|
||||||
|
if (wasLoggedIn) {
|
||||||
|
final result = await authService.signIn(credentials);
|
||||||
|
if (result.isSuccess) {
|
||||||
|
timelineManager.updateTimeline(
|
||||||
|
TimelineIdentifiers.home(), TimelineRefreshType.loadOlder);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_logger.severe('Was not logged in');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -3,32 +3,21 @@ import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart';
|
import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:result_monad/result_monad.dart';
|
|
||||||
|
|
||||||
import 'data/interfaces/connections_repo_intf.dart';
|
import 'app_theme.dart';
|
||||||
import 'data/interfaces/groups_repo.intf.dart';
|
import 'di_initialization.dart';
|
||||||
import 'data/interfaces/hashtag_repo_intf.dart';
|
|
||||||
import 'data/memory/memory_groups_repo.dart';
|
|
||||||
import 'data/objectbox/objectbox_cache.dart';
|
|
||||||
import 'data/objectbox/objectbox_connections_repo.dart';
|
|
||||||
import 'data/objectbox/objectbox_hashtag_repo.dart';
|
|
||||||
import 'globals.dart';
|
import 'globals.dart';
|
||||||
import 'models/TimelineIdentifiers.dart';
|
|
||||||
import 'routes.dart';
|
import 'routes.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';
|
||||||
import 'services/gallery_service.dart';
|
import 'services/gallery_service.dart';
|
||||||
import 'services/hashtag_service.dart';
|
import 'services/hashtag_service.dart';
|
||||||
import 'services/media_upload_attachment_helper.dart';
|
|
||||||
import 'services/notifications_manager.dart';
|
import 'services/notifications_manager.dart';
|
||||||
import 'services/secrets_service.dart';
|
|
||||||
import 'services/setting_service.dart';
|
import 'services/setting_service.dart';
|
||||||
import 'services/timeline_manager.dart';
|
import 'services/timeline_manager.dart';
|
||||||
import 'utils/app_scrolling_behavior.dart';
|
import 'utils/app_scrolling_behavior.dart';
|
||||||
|
|
||||||
final _logger = Logger('Main');
|
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await dotenv.load(fileName: '.env');
|
await dotenv.load(fileName: '.env');
|
||||||
|
@ -41,52 +30,7 @@ void main() async {
|
||||||
print(msg);
|
print(msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
final authService = AuthService();
|
dependencyInjectionInitialization();
|
||||||
final secretsService = SecretsService();
|
|
||||||
final entryManagerService = EntryManagerService();
|
|
||||||
final timelineManager = TimelineManager();
|
|
||||||
final galleryService = GalleryService();
|
|
||||||
|
|
||||||
getIt.registerSingletonAsync(() async {
|
|
||||||
final service = SettingsService();
|
|
||||||
await service.initialize();
|
|
||||||
return service;
|
|
||||||
});
|
|
||||||
|
|
||||||
final objectBoxCache = await ObjectBoxCache.create();
|
|
||||||
getIt.registerSingleton<ObjectBoxCache>(objectBoxCache);
|
|
||||||
getIt.registerSingleton<IConnectionsRepo>(ObjectBoxConnectionsRepo());
|
|
||||||
getIt.registerSingleton<IHashtagRepo>(ObjectBoxHashtagRepo());
|
|
||||||
getIt.registerSingleton<IGroupsRepo>(MemoryGroupsRepo());
|
|
||||||
getIt.registerLazySingleton<ConnectionsManager>(() => ConnectionsManager());
|
|
||||||
getIt.registerLazySingleton<HashtagService>(() => HashtagService());
|
|
||||||
getIt.registerSingleton(galleryService);
|
|
||||||
getIt.registerSingleton<EntryManagerService>(entryManagerService);
|
|
||||||
getIt.registerSingleton<SecretsService>(secretsService);
|
|
||||||
getIt.registerSingleton<AuthService>(authService);
|
|
||||||
getIt.registerSingleton<TimelineManager>(timelineManager);
|
|
||||||
getIt.registerLazySingleton<MediaUploadAttachmentHelper>(
|
|
||||||
() => MediaUploadAttachmentHelper());
|
|
||||||
getIt.registerLazySingleton<NotificationsManager>(
|
|
||||||
() => NotificationsManager());
|
|
||||||
galleryService.getGalleries();
|
|
||||||
|
|
||||||
await secretsService.initialize().andThenSuccessAsync((credentials) async {
|
|
||||||
if (credentials.isEmpty) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final wasLoggedIn = await authService.getStoredLoginState();
|
|
||||||
if (wasLoggedIn) {
|
|
||||||
final result = await authService.signIn(credentials);
|
|
||||||
if (result.isSuccess) {
|
|
||||||
timelineManager.updateTimeline(
|
|
||||||
TimelineIdentifiers.home(), TimelineRefreshType.loadOlder);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_logger.severe('Was not logged in');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
runApp(const App());
|
runApp(const App());
|
||||||
}
|
}
|
||||||
|
@ -97,6 +41,8 @@ class App extends StatelessWidget {
|
||||||
// This widget is the root of your application.
|
// This widget is the root of your application.
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
return AnimatedBuilder(
|
||||||
|
builder: (context, child) {
|
||||||
return Portal(
|
return Portal(
|
||||||
child: MultiProvider(
|
child: MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
|
@ -132,9 +78,9 @@ class App extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: MaterialApp.router(
|
child: MaterialApp.router(
|
||||||
theme: ThemeData(
|
theme: AppTheme.light,
|
||||||
primarySwatch: Colors.indigo,
|
darkTheme: AppTheme.dark,
|
||||||
),
|
themeMode: getIt<SettingsService>().themeMode,
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
scrollBehavior: AppScrollingBehavior(),
|
scrollBehavior: AppScrollingBehavior(),
|
||||||
routerDelegate: appRouter.routerDelegate,
|
routerDelegate: appRouter.routerDelegate,
|
||||||
|
@ -143,5 +89,8 @@ class App extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
animation: getIt<SettingsService>(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,11 @@ import 'screens/follow_request_adjudication_screen.dart';
|
||||||
import 'screens/gallery_browsers_screen.dart';
|
import 'screens/gallery_browsers_screen.dart';
|
||||||
import 'screens/gallery_screen.dart';
|
import 'screens/gallery_screen.dart';
|
||||||
import 'screens/home.dart';
|
import 'screens/home.dart';
|
||||||
|
import 'screens/menus_screen.dart';
|
||||||
import 'screens/notifications_screen.dart';
|
import 'screens/notifications_screen.dart';
|
||||||
import 'screens/post_screen.dart';
|
import 'screens/post_screen.dart';
|
||||||
import 'screens/profile_screen.dart';
|
import 'screens/profile_screen.dart';
|
||||||
|
import 'screens/settings_screen.dart';
|
||||||
import 'screens/sign_in.dart';
|
import 'screens/sign_in.dart';
|
||||||
import 'screens/splash.dart';
|
import 'screens/splash.dart';
|
||||||
import 'screens/user_posts_screen.dart';
|
import 'screens/user_posts_screen.dart';
|
||||||
|
@ -20,13 +22,14 @@ class ScreenPaths {
|
||||||
static String connectHandle = '/connect';
|
static String connectHandle = '/connect';
|
||||||
static String contacts = '/contacts';
|
static String contacts = '/contacts';
|
||||||
static String splash = '/splash';
|
static String splash = '/splash';
|
||||||
|
static String menu = '/menu';
|
||||||
|
static String settings = '/settings';
|
||||||
static String timelines = '/';
|
static String timelines = '/';
|
||||||
static String gallery = '/gallery';
|
static String gallery = '/gallery';
|
||||||
static String profile = '/profile';
|
static String profile = '/profile';
|
||||||
static String notifications = '/notifications';
|
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 userProfile = '/user_profile';
|
static String userProfile = '/user_profile';
|
||||||
static String userPosts = '/user_posts';
|
static String userPosts = '/user_posts';
|
||||||
}
|
}
|
||||||
|
@ -90,6 +93,20 @@ final appRouter = GoRouter(
|
||||||
child: ProfileScreen(),
|
child: ProfileScreen(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: ScreenPaths.menu,
|
||||||
|
name: ScreenPaths.menu,
|
||||||
|
pageBuilder: (context, state) => NoTransitionPage(
|
||||||
|
child: MenusScreen(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: ScreenPaths.settings,
|
||||||
|
name: ScreenPaths.settings,
|
||||||
|
pageBuilder: (context, state) => NoTransitionPage(
|
||||||
|
child: SettingsScreen(),
|
||||||
|
),
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: ScreenPaths.gallery,
|
path: ScreenPaths.gallery,
|
||||||
name: ScreenPaths.gallery,
|
name: ScreenPaths.gallery,
|
||||||
|
|
|
@ -3,8 +3,8 @@ 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/padding.dart';
|
import '../controls/padding.dart';
|
||||||
|
import '../controls/standard_appbar.dart';
|
||||||
import '../services/gallery_service.dart';
|
import '../services/gallery_service.dart';
|
||||||
|
|
||||||
class GalleryBrowsersScreen extends StatelessWidget {
|
class GalleryBrowsersScreen extends StatelessWidget {
|
||||||
|
@ -15,13 +15,12 @@ class GalleryBrowsersScreen extends StatelessWidget {
|
||||||
_logger.finest('Building');
|
_logger.finest('Building');
|
||||||
final service = context.watch<GalleryService>();
|
final service = context.watch<GalleryService>();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
appBar: StandardAppBar.build(context, 'Galleries'),
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
await service.updateGalleries();
|
await service.updateGalleries();
|
||||||
},
|
},
|
||||||
child: buildBody(context, service)),
|
child: buildBody(context, service),
|
||||||
bottomNavigationBar: const AppBottomNavBar(
|
|
||||||
currentButton: NavBarButtons.gallery,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:logging/logging.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../controls/padding.dart';
|
import '../controls/padding.dart';
|
||||||
|
import '../controls/standard_appbar.dart';
|
||||||
import '../serializers/friendica/image_entry_friendica_extensions.dart';
|
import '../serializers/friendica/image_entry_friendica_extensions.dart';
|
||||||
import '../services/gallery_service.dart';
|
import '../services/gallery_service.dart';
|
||||||
import 'image_viewer_screen.dart';
|
import 'image_viewer_screen.dart';
|
||||||
|
@ -20,9 +21,7 @@ class GalleryScreen extends StatelessWidget {
|
||||||
_logger.finest('Building');
|
_logger.finest('Building');
|
||||||
final service = context.watch<GalleryService>();
|
final service = context.watch<GalleryService>();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: StandardAppBar.build(context, galleryName),
|
||||||
title: Text(galleryName),
|
|
||||||
),
|
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
await service.updateGalleryImageList(galleryName);
|
await service.updateGalleryImageList(galleryName);
|
||||||
|
|
|
@ -81,8 +81,8 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
context.push('/post/new');
|
context.push('/post/new');
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.add,
|
Icons.edit,
|
||||||
color: Theme.of(context).primaryColor,
|
color: Theme.of(context).textTheme.bodyText1!.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:friendica_portal/globals.dart';
|
||||||
|
import 'package:friendica_portal/services/auth_service.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
|
import '../controls/app_bottom_nav_bar.dart';
|
||||||
|
import '../routes.dart';
|
||||||
|
|
||||||
|
class MenusScreen extends StatelessWidget {
|
||||||
|
static const menuButtonWidth = 350.0;
|
||||||
|
static const menuButtonHeight = 125.0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final menuItems = [
|
||||||
|
buildMenuButton('Gallery', () => context.pushNamed(ScreenPaths.gallery)),
|
||||||
|
buildMenuButton('Profile', () => context.pushNamed(ScreenPaths.profile)),
|
||||||
|
buildMenuButton(
|
||||||
|
'Settings', () => context.pushNamed(ScreenPaths.settings)),
|
||||||
|
buildMenuButton('Logout', () async {
|
||||||
|
final confirm = await showYesNoDialog(context, 'Log out account?');
|
||||||
|
if (confirm == true) {
|
||||||
|
await getIt<AuthService>().signOut();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
return Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: GridView(
|
||||||
|
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
|
mainAxisExtent: menuButtonHeight,
|
||||||
|
maxCrossAxisExtent: menuButtonWidth,
|
||||||
|
),
|
||||||
|
children: menuItems,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
bottomNavigationBar: const AppBottomNavBar(
|
||||||
|
currentButton: NavBarButtons.menu,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildMenuButton(String title, Function() onPressed) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: Text(title),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,8 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../controls/app_bottom_nav_bar.dart';
|
import '../controls/standard_appbar.dart';
|
||||||
import '../controls/padding.dart';
|
|
||||||
import '../services/auth_service.dart';
|
import '../services/auth_service.dart';
|
||||||
import '../services/setting_service.dart';
|
|
||||||
|
|
||||||
class ProfileScreen extends StatefulWidget {
|
class ProfileScreen extends StatefulWidget {
|
||||||
const ProfileScreen({super.key});
|
const ProfileScreen({super.key});
|
||||||
|
@ -16,41 +14,18 @@ class ProfileScreen extends StatefulWidget {
|
||||||
class _ProfileScreenState extends State<ProfileScreen> {
|
class _ProfileScreenState extends State<ProfileScreen> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final settings = context.watch<SettingsService>();
|
|
||||||
final authService = context.watch<AuthService>();
|
final authService = context.watch<AuthService>();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: StandardAppBar.build(context, 'Profile'),
|
||||||
title: Text('Profile'),
|
|
||||||
),
|
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Checkbox(
|
|
||||||
value: settings.lowBandwidthMode,
|
|
||||||
onChanged: (value) =>
|
|
||||||
settings.lowBandwidthMode = value ?? false,
|
|
||||||
),
|
|
||||||
Text('Low Bandwidth Mode'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Text(
|
Text(
|
||||||
'Profile: ${authService.currentClient.fold(onSuccess: (client) => client.credentials.handle, onError: (error) => 'Error Getting Profile')}'),
|
'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,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../controls/standard_appbar.dart';
|
||||||
|
import '../services/setting_service.dart';
|
||||||
|
import '../utils/theme_mode_extensions.dart';
|
||||||
|
|
||||||
|
class SettingsScreen extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final settings = context.watch<SettingsService>();
|
||||||
|
return Scaffold(
|
||||||
|
appBar: StandardAppBar.build(context, 'Settings'),
|
||||||
|
body: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
buildLowBandwidthWidget(settings),
|
||||||
|
buildThemeWidget(settings),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildLowBandwidthWidget(SettingsService settings) {
|
||||||
|
return ListTile(
|
||||||
|
title: const Text('Low bandwidth mode'),
|
||||||
|
trailing: Checkbox(
|
||||||
|
onChanged: (value) {
|
||||||
|
settings.lowBandwidthMode = value ?? false;
|
||||||
|
},
|
||||||
|
value: settings.lowBandwidthMode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildThemeWidget(SettingsService settings) {
|
||||||
|
return ListTile(
|
||||||
|
title: const Text('Dark Mode Theme:'),
|
||||||
|
trailing: DropdownButton<ThemeMode>(
|
||||||
|
value: settings.themeMode,
|
||||||
|
items: ThemeMode.values
|
||||||
|
.map((m) => DropdownMenuItem(value: m, child: Text(m.toLabel())))
|
||||||
|
.toList(),
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value != null) {
|
||||||
|
settings.themeMode = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../utils/theme_mode_extensions.dart';
|
||||||
|
|
||||||
class SettingsService extends ChangeNotifier {
|
class SettingsService extends ChangeNotifier {
|
||||||
late final SharedPreferences _prefs;
|
late final SharedPreferences _prefs;
|
||||||
var _initialized = false;
|
var _initialized = false;
|
||||||
|
@ -17,14 +19,26 @@ class SettingsService extends ChangeNotifier {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _themeMode = ThemeMode.system;
|
||||||
|
|
||||||
|
ThemeMode get themeMode => _themeMode;
|
||||||
|
|
||||||
|
set themeMode(ThemeMode mode) {
|
||||||
|
_themeMode = mode;
|
||||||
|
_prefs.setString(_themeModeKey, _themeMode.name);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> initialize() async {
|
Future<void> initialize() async {
|
||||||
if (_initialized) {
|
if (_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_prefs = await SharedPreferences.getInstance();
|
_prefs = await SharedPreferences.getInstance();
|
||||||
_lowBandwidthMode = _prefs.getBool(_lowBandwidthModeKey) ?? false;
|
_lowBandwidthMode = _prefs.getBool(_lowBandwidthModeKey) ?? false;
|
||||||
|
_themeMode = ThemeModeExtensions.parse(_prefs.getString(_themeModeKey));
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const _lowBandwidthModeKey = 'LowBandwidthMode';
|
const _lowBandwidthModeKey = 'LowBandwidthMode';
|
||||||
|
const _themeModeKey = 'ThemeMode';
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
extension ThemeModeExtensions on ThemeMode {
|
||||||
|
static ThemeMode parse(String? themeModeString) =>
|
||||||
|
ThemeMode.values.firstWhere(
|
||||||
|
(m) => m.name == themeModeString,
|
||||||
|
orElse: () => ThemeMode.system,
|
||||||
|
);
|
||||||
|
|
||||||
|
String toLabel() {
|
||||||
|
switch (this) {
|
||||||
|
case ThemeMode.system:
|
||||||
|
return 'System';
|
||||||
|
case ThemeMode.light:
|
||||||
|
return 'Light';
|
||||||
|
case ThemeMode.dark:
|
||||||
|
return 'Dark';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Ładowanie…
Reference in New Issue