Add initial basic focus mode implementation

merge-requests/67/merge
Hank Grabowski 2024-07-24 11:42:24 -04:00
rodzic 0e18e02b3a
commit f5241a72fa
5 zmienionych plików z 332 dodań i 253 usunięć

Wyświetl plik

@ -0,0 +1,55 @@
import 'dart:async';
import 'package:flutter/material.dart';
import '../utils/dateutils.dart';
class AppBottomFocusModeStatus extends StatefulWidget {
final DateTime? disableTime;
const AppBottomFocusModeStatus({super.key, required this.disableTime});
@override
State<AppBottomFocusModeStatus> createState() =>
_AppBottomFocusModeStatusState();
}
class _AppBottomFocusModeStatusState extends State<AppBottomFocusModeStatus> {
Timer? updateTimer;
Duration? timeUntil;
@override
void initState() {
super.initState();
_updateTimeUntil();
updateTimer = Timer.periodic(Duration(seconds: 1), (_) {
setState(() {
_updateTimeUntil();
});
});
}
@override
void dispose() {
print('Disposing');
updateTimer?.cancel();
super.dispose();
}
void _updateTimeUntil() {
timeUntil = widget.disableTime?.difference(DateTime.now());
}
@override
Widget build(BuildContext context) {
final title = timeUntil == null
? 'Focus Mode'
: 'Focus Mode for ${timeUntil!.simpleLabel}';
return Text(
title,
style: Theme.of(context).textTheme.headlineSmall!.copyWith(
fontWeight: FontWeight.bold,
),
);
}
}

Wyświetl plik

@ -5,6 +5,7 @@ import 'package:logging/logging.dart';
import '../globals.dart';
import '../routes.dart';
import '../services/auth_service.dart';
import 'focus_mode_menu_item.dart';
import 'login_aware_cached_network_image.dart';
class StandardAppDrawer extends StatelessWidget {
@ -62,6 +63,7 @@ class StandardAppDrawer extends StatelessWidget {
'Manage Profiles',
() => context.pushNamed(ScreenPaths.manageProfiles),
),
const FocusModeMenuItem(),
const Divider(),
buildMenuButton(
context,

Wyświetl plik

@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart' as fr;
import 'package:go_router/go_router.dart';
import 'package:logging/logging.dart';
import 'package:media_kit/media_kit.dart';
import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart';
@ -8,6 +10,7 @@ import 'package:provider/provider.dart';
import 'app_theme.dart';
import 'di_initialization.dart';
import 'globals.dart';
import 'riverpod_controllers/focus_mode.dart';
import 'routes.dart';
import 'services/auth_service.dart';
import 'services/blocks_manager.dart';
@ -51,7 +54,7 @@ void main() async {
// enabled: !kReleaseMode && enablePreview,
// builder: (context) => const App(),
// ));
runApp(const App());
runApp(const fr.ProviderScope(child: App()));
}
Future<void> setupPackageInfoAndUserAgent() async {
@ -60,13 +63,45 @@ Future<void> setupPackageInfoAndUserAgent() async {
userAgent = 'Relatica/$appVersion';
}
class App extends StatelessWidget {
class App extends fr.ConsumerStatefulWidget {
const App({super.key});
// This widget is the root of your application.
@override
fr.ConsumerState<App> createState() => _AppState();
}
class _AppState extends fr.ConsumerState<App> {
@override
Widget build(BuildContext context) {
final settingsService = getIt<SettingsService>();
final authService = getIt<AccountsService>();
final appRouter = GoRouter(
initialLocation: ScreenPaths.timelines,
debugLogDiagnostics: true,
refreshListenable: authService,
redirect: (context, state) async {
final loggedIn = authService.loggedIn;
final focusMode = ref.read(focusModeProvider);
print('Focus mode? $focusMode');
if (!loggedIn && authService.initializing) {
return ScreenPaths.splash;
}
if (!loggedIn && !allowedLoggedOut.contains(state.uri.toString())) {
return ScreenPaths.signin;
}
if (loggedIn && allowedLoggedOut.contains(state.uri.toString())) {
return ScreenPaths.timelines;
}
return null;
},
routes: routes,
);
return AnimatedBuilder(
builder: (context, child) {
Logger.root.level = settingsService.logLevel;

Wyświetl plik

@ -1,6 +1,5 @@
import 'package:go_router/go_router.dart';
import 'globals.dart';
import 'models/interaction_type_enum.dart';
import 'screens/blocks_screen.dart';
import 'screens/circle_add_users_screen.dart';
@ -29,7 +28,6 @@ import 'screens/sign_in.dart';
import 'screens/splash.dart';
import 'screens/user_posts_screen.dart';
import 'screens/user_profile_screen.dart';
import 'services/auth_service.dart';
class ScreenPaths {
static String blocks = '/blocks';
@ -56,35 +54,13 @@ class ScreenPaths {
}
bool needAuthChangeInitialized = true;
final _authService = getIt<AccountsService>();
final allowedLoggedOut = [
ScreenPaths.splash,
ScreenPaths.signin,
ScreenPaths.signup
];
final appRouter = GoRouter(
initialLocation: ScreenPaths.timelines,
debugLogDiagnostics: true,
refreshListenable: _authService,
redirect: (context, state) async {
final loggedIn = _authService.loggedIn;
if (!loggedIn && _authService.initializing) {
return ScreenPaths.splash;
}
if (!loggedIn && !allowedLoggedOut.contains(state.uri.toString())) {
return ScreenPaths.signin;
}
if (loggedIn && allowedLoggedOut.contains(state.uri.toString())) {
return ScreenPaths.timelines;
}
return null;
},
routes: [
final routes = [
GoRoute(
path: ScreenPaths.blocks,
name: ScreenPaths.blocks,
@ -129,8 +105,8 @@ final appRouter = GoRouter(
GoRoute(
path: '/connect/:id',
name: ScreenPaths.connectHandle,
builder: (context, state) => FollowRequestAdjudicationScreen(
userId: state.pathParameters['id']!),
builder: (context, state) =>
FollowRequestAdjudicationScreen(userId: state.pathParameters['id']!),
),
GoRoute(
path: ScreenPaths.timelines,
@ -158,8 +134,8 @@ final appRouter = GoRouter(
GoRoute(
name: ScreenPaths.thread,
path: ScreenPaths.thread,
builder: (context, state) => MessageThreadScreen(
parentThreadId: state.uri.queryParameters['uri']!),
builder: (context, state) =>
MessageThreadScreen(parentThreadId: state.uri.queryParameters['uri']!),
),
GoRoute(
name: ScreenPaths.circleManagement,
@ -323,4 +299,4 @@ final appRouter = GoRouter(
child: LogViewerScreen(),
),
),
]);
];

Wyświetl plik

@ -1,7 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import 'package:relatica/controls/focus_mode_status_headline.dart';
import 'package:relatica/riverpod_controllers/focus_mode.dart';
import '../controls/app_bottom_nav_bar.dart';
import '../controls/linear_status_indicator.dart';
@ -16,14 +19,14 @@ import '../services/network_status_service.dart';
import '../services/timeline_manager.dart';
import '../utils/active_profile_selector.dart';
class HomeScreen extends StatefulWidget {
class HomeScreen extends ConsumerStatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
ConsumerState<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
class _HomeScreenState extends ConsumerState<HomeScreen> {
final _logger = Logger('$HomeScreen');
TimelineIdentifiers currentTimeline = TimelineIdentifiers.home();
@ -49,8 +52,12 @@ class _HomeScreenState extends State<HomeScreen> {
_logger.finest('Build');
final accountService = getIt<AccountsService>();
final nss = getIt<NetworkStatusService>();
final focusMode = ref.watch(focusModeProvider);
final timeline = TimelinePanel(timeline: currentTimeline);
final timeline = TimelinePanel(
timeline: focusMode.enabled
? TimelineIdentifiers.myPosts()
: currentTimeline);
return Scaffold(
appBar: AppBar(
@ -65,7 +72,9 @@ class _HomeScreenState extends State<HomeScreen> {
})
: null,
backgroundColor: Theme.of(context).canvasColor,
title: buildTimelineSelector(context),
title: focusMode.enabled
? AppBottomFocusModeStatus(disableTime: focusMode.disableTime)
: buildTimelineSelector(context),
),
body: Center(
child: Column(
@ -78,7 +87,9 @@ class _HomeScreenState extends State<HomeScreen> {
),
),
drawer: const StandardAppDrawer(),
bottomNavigationBar: AppBottomNavBar(
bottomNavigationBar: focusMode.enabled
? null
: AppBottomNavBar(
currentButton: NavBarButtons.timelines,
onHomeButtonReclick: () => timeline.scrollToTop(),
),