Skip to content

Commit 86130d0

Browse files
committed
bug fixes --no-bump
1 parent 3bc0177 commit 86130d0

15 files changed

Lines changed: 490 additions & 187 deletions

File tree

devtools_options.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
description: This file stores settings for Dart & Flutter DevTools.
2+
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
3+
extensions:
4+
- hive_ce: true
5+
- get_it: true

lib/features/api/repositories/fpapi.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ class FPApiRequests {
679679
}
680680

681681
final decodedres = jsonDecode(response);
682-
if (decodedres != null && decodedres.toString().contains('dislike')) {
682+
if (decodedres != null && decodedres.toString().contains('like')) {
683683
return 'success';
684684
}
685685

@@ -696,7 +696,7 @@ class FPApiRequests {
696696
}
697697

698698
final decodedres = jsonDecode(response);
699-
if (decodedres != null && decodedres.toString().contains('like')) {
699+
if (decodedres != null && decodedres.toString().contains('dislike')) {
700700
return 'success';
701701
}
702702

lib/features/download/components/fp_download_dialog.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_riverpod/flutter_riverpod.dart';
3-
import 'package:go_router/go_router.dart';
43

54
import 'package:floaty/features/api/models/definitions.dart';
65
import 'package:floaty/features/download/repositories/fp_download_provider.dart';

lib/features/download/controllers/fp_download_service.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,21 @@ class FPDownloadService {
119119
const linuxSettings = LinuxInitializationSettings(
120120
defaultActionName: 'Open notification',
121121
);
122+
// Provide Windows initialization settings when running on Windows
123+
final windowsSettings = Platform.isWindows
124+
? WindowsInitializationSettings(
125+
appName: 'Floaty',
126+
appUserModelId: 'uk.bw86.floaty',
127+
guid: 'd2f7b3e5-1c7a-4b0a-8c2f-3e8b9d1a2b3c',
128+
)
129+
: null;
122130

123131
final initSettings = InitializationSettings(
124132
android: androidSettings,
125133
iOS: iosSettings,
126134
macOS: macosSettings,
127135
linux: linuxSettings,
136+
windows: windowsSettings,
128137
);
129138

130139
await _notificationsPlugin.initialize(initSettings);

lib/features/home/views/home_screen.dart

Lines changed: 233 additions & 81 deletions
Large diffs are not rendered by default.

lib/features/player/components/custom_player/custom_player.dart

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:floaty/features/player/components/custom_player/fullscreen_playe
66
import 'package:floaty/features/player/components/custom_player/pip_overlay.dart';
77
import 'package:floaty/features/player/controllers/media_player_service.dart';
88
import 'package:floaty/features/player/models/video_quality.dart';
9+
import 'package:floaty/settings.dart';
910
import 'package:flutter/material.dart';
1011
import 'package:flutter/services.dart';
1112
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -156,6 +157,7 @@ class _CustomPlayerState extends ConsumerState<CustomPlayer>
156157
bool _volumeDragging = false;
157158
bool _buffering = false;
158159
double _playbackSpeed = 1.0;
160+
bool _incrementPlaybackSpeed = false;
159161
late final AnimationController _animationController;
160162
Timer? _hideControlsTimer;
161163
late final MediaPlayerService mediaService;
@@ -256,7 +258,15 @@ class _CustomPlayerState extends ConsumerState<CustomPlayer>
256258
_buffering = mediaService.buffering;
257259

258260
_setupPlayerListeners();
259-
_initBrightnessAndVolume();
261+
262+
// Perform async initialization without making initState async.
263+
_asyncInit();
264+
}
265+
266+
Future<void> _asyncInit() async {
267+
_incrementPlaybackSpeed =
268+
await settings.getBool('increment_playback_speed');
269+
await _initBrightnessAndVolume();
260270
}
261271

262272
Future<void> _initBrightnessAndVolume() async {
@@ -1535,9 +1545,9 @@ class _CustomPlayerState extends ConsumerState<CustomPlayer>
15351545
child: Center(
15361546
child: Slider(
15371547
value: _playbackSpeed,
1538-
min: 0.25,
1548+
min: _incrementPlaybackSpeed ? 0.3 : 0.25,
15391549
max: 4.0,
1540-
divisions: 15,
1550+
divisions: _incrementPlaybackSpeed ? 37 : 15,
15411551
label: '${_playbackSpeed.toStringAsFixed(2)}x',
15421552
onChanged: (value) {
15431553
setState(() => _playbackSpeed = value);
@@ -1570,9 +1580,9 @@ class _CustomPlayerState extends ConsumerState<CustomPlayer>
15701580
child: Center(
15711581
child: Slider(
15721582
value: _playbackSpeed,
1573-
min: 0.25,
1583+
min: _incrementPlaybackSpeed ? 0.3 : 0.25,
15741584
max: 4.0,
1575-
divisions: 15,
1585+
divisions: _incrementPlaybackSpeed ? 37 : 15,
15761586
label: '${_playbackSpeed.toStringAsFixed(2)}x',
15771587
onChanged: (value) {
15781588
if (setModalState != null) {

lib/features/post/views/post_screen.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,9 +1120,9 @@ class _VideoDetailPageState extends ConsumerState<VideoDetailPage> {
11201120
GestureDetector(
11211121
onTap: () {
11221122
if (post.creator?.urlname == post.channel?.urlname) {
1123-
context.go('/channel/${post.creator?.urlname}');
1123+
context.push('/channel/${post.creator?.urlname}');
11241124
} else {
1125-
context.go(
1125+
context.push(
11261126
'/channel/${post.creator?.urlname}/${post.channel?.urlname}');
11271127
}
11281128
},
@@ -1478,10 +1478,11 @@ class _VideoDetailPageState extends ConsumerState<VideoDetailPage> {
14781478
splashFactory: InkRipple.splashFactory,
14791479
overlayColor: Colors.grey[800],
14801480
),
1481-
child: const Text(
1481+
child: Text(
14821482
'CANCEL',
14831483
style: TextStyle(
14841484
fontWeight: FontWeight.bold,
1485+
color: theme.textTheme.bodyMedium?.color,
14851486
),
14861487
),
14871488
),
@@ -1515,7 +1516,7 @@ class _VideoDetailPageState extends ConsumerState<VideoDetailPage> {
15151516
style: TextStyle(
15161517
color: _currentLength >= 3 &&
15171518
_currentLength <= 4500
1518-
? Colors.white
1519+
? colorScheme.primary
15191520
: Colors.grey[600],
15201521
fontWeight: FontWeight.bold,
15211522
),

lib/features/router/controllers/router.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ final GoRouter routerController = GoRouter(
298298
return null;
299299
} else {
300300
// User has never authenticated and is offline - they can only access offline routes
301-
final isOfflineRoute = currentPath == '/offline-library' ||
301+
final isOfflineRoute = currentPath == '/offline' ||
302302
(currentPath.startsWith('/post/') &&
303303
state.extra is Map &&
304304
(state.extra as Map)['isOffline'] == true);
@@ -308,7 +308,7 @@ final GoRouter routerController = GoRouter(
308308
}
309309

310310
// Redirect to offline library since they can't login anyway
311-
return '/offline-library';
311+
return '/offline';
312312
}
313313
}
314314

@@ -331,7 +331,7 @@ final GoRouter routerController = GoRouter(
331331
// Allow them to stay in the app but redirect to offline library
332332
// unless they're already on a safe route
333333

334-
final isOfflineRoute = currentPath == '/offline-library' ||
334+
final isOfflineRoute = currentPath == '/offline' ||
335335
(currentPath.startsWith('/post/') &&
336336
state.extra is Map &&
337337
(state.extra as Map)['isOffline'] == true);
@@ -346,15 +346,15 @@ final GoRouter routerController = GoRouter(
346346
// This way they can still watch their downloaded videos
347347
debugPrint(
348348
'Session expired but user has offline access - redirecting to offline library');
349-
return '/offline-library';
349+
return '/offline';
350350
}
351351

352352
// Already on a safe route, let them stay
353353
return null;
354354
}
355355

356356
// Allow access to offline content routes even without any authentication
357-
final isOfflineRoute = currentPath == '/offline-library' ||
357+
final isOfflineRoute = currentPath == '/offline' ||
358358
(currentPath.startsWith('/post/') &&
359359
state.extra is Map &&
360360
(state.extra as Map)['isOffline'] == true);

lib/features/router/views/root_layout.dart

Lines changed: 91 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import 'package:floaty/shared/components/switcher.dart';
88
import 'package:floaty/whitelabels.dart';
99
import 'package:flutter/material.dart';
1010
import 'package:flutter_riverpod/flutter_riverpod.dart';
11+
import 'package:go_router/go_router.dart';
1112

1213
import 'package:floaty/features/api/models/definitions.dart';
1314
import 'package:floaty/shared/controllers/root_provider.dart';
1415
import 'package:floaty/features/player/components/custom_player/mini_player_overlay.dart';
1516
import 'package:floaty/features/player/controllers/media_player_service.dart';
17+
import 'package:hive_ce_flutter/hive_flutter.dart';
1618
// No router import here — RootLayout is a plain shell widget.
1719

1820
// RootLayout is a plain shell widget. A single global key is used so
@@ -36,6 +38,7 @@ class RootLayoutState extends ConsumerState<RootLayout>
3638
bool? _lastSidebarCollapsed;
3739
bool _textGuardInitialized = false;
3840
bool updateReady = updatercontroller.updateReady;
41+
int _selectedIndex = 0;
3942
@override
4043
void initState() {
4144
super.initState();
@@ -81,6 +84,12 @@ class RootLayoutState extends ConsumerState<RootLayout>
8184
final screenWidth = MediaQuery.of(context).size.width;
8285
isSmallScreen = screenWidth < 600;
8386
bool subed = false;
87+
final settingsBox = Hive.box('settings');
88+
//TODO: put back
89+
final bottomNavEnabled = false;
90+
// final bottomNavEnabled =
91+
// settingsBox.get('bottom_navigation', defaultValue: true) as bool;
92+
final useBottomNav = isSmallScreen && bottomNavEnabled;
8493

8594
final isSidebarCollapsed = isSmallScreen ? false : rootState.isCollapsed;
8695

@@ -288,24 +297,54 @@ class RootLayoutState extends ConsumerState<RootLayout>
288297
surfaceTintColor: colorScheme.surfaceContainer,
289298
title: rootState.appBarTitle,
290299
actions: rootState.appBarActions,
291-
leading: rootState.appBarLeading ??
292-
(isSmallScreen
293-
? IconButton(
294-
icon: const Icon(Icons.menu),
295-
onPressed: () {
296-
scaffoldKey.currentState?.openDrawer();
297-
},
298-
)
299-
: (Navigator.of(context).canPop()
300-
? IconButton(
301-
icon: const Icon(Icons.arrow_back),
302-
onPressed: () {
303-
Navigator.of(context).pop();
304-
},
305-
)
306-
: null)),
300+
leading: (() {
301+
if (rootState.appBarLeading != null) return rootState.appBarLeading;
302+
if (isSmallScreen) {
303+
// On small screens:
304+
// - If bottom nav is NOT enabled, show the menu button.
305+
// - If bottom nav IS enabled, show a back button except on root routes.
306+
if (!useBottomNav) {
307+
return IconButton(
308+
icon: const Icon(Icons.menu),
309+
onPressed: () {
310+
scaffoldKey.currentState?.openDrawer();
311+
},
312+
);
313+
}
314+
315+
final currentPath = GoRouter.of(context).state.uri.path;
316+
const rootRoutes = [
317+
'/home',
318+
'/browse',
319+
'/history',
320+
'/offline',
321+
'/more'
322+
];
323+
final isRootRoute =
324+
rootRoutes.any((r) => currentPath.startsWith(r));
325+
if (isRootRoute) return null;
326+
return IconButton(
327+
icon: const Icon(Icons.arrow_back),
328+
onPressed: () {
329+
if (GoRouter.of(context).canPop()) {
330+
context.pop();
331+
} else {
332+
context.go('/home');
333+
}
334+
},
335+
);
336+
}
337+
return Navigator.of(context).canPop()
338+
? IconButton(
339+
icon: const Icon(Icons.arrow_back),
340+
onPressed: () {
341+
Navigator.of(context).pop();
342+
},
343+
)
344+
: null;
345+
}()),
307346
),
308-
drawer: isSmallScreen ? sidebar : null,
347+
drawer: (isSmallScreen && !useBottomNav) ? sidebar : null,
309348
body: SafeArea(
310349
child: Row(
311350
children: [
@@ -330,6 +369,41 @@ class RootLayoutState extends ConsumerState<RootLayout>
330369
],
331370
),
332371
),
372+
bottomNavigationBar: useBottomNav
373+
? NavigationBar(
374+
selectedIndex: _selectedIndex,
375+
onDestinationSelected: (idx) {
376+
String route = '/home';
377+
switch (idx) {
378+
case 0:
379+
route = '/home';
380+
break;
381+
case 1:
382+
route = '/history';
383+
break;
384+
case 2:
385+
route = '/browse';
386+
break;
387+
case 3:
388+
route = '/more';
389+
break;
390+
}
391+
setState(() {
392+
_selectedIndex = idx;
393+
});
394+
context.go(route);
395+
},
396+
destinations: const [
397+
NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
398+
NavigationDestination(
399+
icon: Icon(Icons.history), label: 'History'),
400+
NavigationDestination(
401+
icon: Icon(Icons.view_carousel), label: 'Browse'),
402+
NavigationDestination(
403+
icon: Icon(Icons.more_horiz), label: 'More'),
404+
],
405+
)
406+
: null,
333407
);
334408
}
335409
}

lib/features/settings/views/settings_screen.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,10 @@ class _PlayerSettingsScreenState extends State<PlayerSettingsScreen> {
11591159
title: 'Pause upon entering background',
11601160
settingkey: 'pause_on_background',
11611161
),
1162+
const ToggleSetting(
1163+
title: 'Increment playback speed by 0.1x',
1164+
settingkey: 'increment_playback_speed',
1165+
),
11621166
if (!Platform.isAndroid && !Platform.isIOS)
11631167
const ToggleSetting(
11641168
title: 'Discord RPC',
@@ -1345,6 +1349,12 @@ class _AppearanceSettingsScreenState extends State<AppearanceSettingsScreen> {
13451349
title: 'Old UI components from old Floatplane design.',
13461350
settingkey: 'legacy_ui',
13471351
),
1352+
//TODO: put back
1353+
// const ToggleSetting(
1354+
// title: 'Bottom Navigation on small screens.',
1355+
// settingkey: 'bottom_navigation',
1356+
// defaultvalue: true,
1357+
// ),
13481358
],
13491359
);
13501360
},

0 commit comments

Comments
 (0)