Add launch-time notification permission prompt and UI polish
Build APK / build (push) Successful in 6m20s

- Request POST_NOTIFICATIONS once on first app launch, with a
  plain-language rationale dialog shown before the OS prompt
  (permission_handler), since upload/download progress relies on it.
- ShareUploadView no longer shows "More tabs" - there's nowhere useful
  for it to go mid-upload.
- FloatingBottomNavBar's pill scrolls horizontally instead of
  overflowing when the visible tab set doesn't fit.
- Settings account card: drop the separate server-address row and its
  globe icon, showing the host inline with the quota percentage/
  "Unlimited storage" text instead (left-aligned, same size).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-18 16:52:16 -04:00
co-authored by Claude Sonnet 5
parent b1400e399f
commit dd0c27035a
9 changed files with 211 additions and 91 deletions
+26 -34
View File
@@ -80,28 +80,6 @@ class AccountView extends StatelessWidget {
const SizedBox(height: 16),
const Divider(height: 1),
const SizedBox(height: 16),
Row(
children: [
Icon(
Icons.public_rounded,
size: 18,
color: colorScheme.onSurfaceVariant,
),
const SizedBox(width: 8),
Expanded(
child: Text(
Uri.tryParse(provider.serverUrl)?.host ??
provider.serverUrl,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.bodyMedium?.copyWith(
color: colorScheme.onSurfaceVariant,
),
),
),
],
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -135,19 +113,33 @@ class AccountView extends StatelessWidget {
),
),
const SizedBox(height: 8),
Align(
alignment: Alignment.centerRight,
child: Text(
quota != null
? (quota.totalBytes > 0
? '${(quota.usagePercentage * 100).toStringAsFixed(1)}% used'
: 'Unlimited storage')
: '',
style: theme.textTheme.bodySmall?.copyWith(
color: colorScheme.onSurfaceVariant,
fontSize: 11,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
Uri.tryParse(provider.serverUrl)?.host ??
provider.serverUrl,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.bodySmall?.copyWith(
color: colorScheme.onSurfaceVariant,
fontSize: 11,
),
),
),
),
Text(
quota != null
? (quota.totalBytes > 0
? '${(quota.usagePercentage * 100).toStringAsFixed(1)}% used'
: 'Unlimited storage')
: '',
style: theme.textTheme.bodySmall?.copyWith(
color: colorScheme.onSurfaceVariant,
fontSize: 11,
),
),
],
),
if (quota != null && quota.groups.isNotEmpty) ...[
const SizedBox(height: 16),
+7 -6
View File
@@ -10,7 +10,6 @@ import '../services/upload_service.dart';
import '../widgets/breadcrumbs.dart';
import '../widgets/item_icon.dart';
import '../widgets/marquee_title.dart';
import '../widgets/more_tabs_button.dart';
import '../widgets/profile_avatar_button.dart';
import '../widgets/segmented_icon_toggle.dart';
import '../widgets/sort_menu_button.dart';
@@ -413,11 +412,13 @@ class _ShareUploadViewState extends State<ShareUploadView> {
body: SyncedHeaderScaffold(
scrollController: _scrollController,
provider: provider,
// Same trailing actions as every other tab - no bespoke close
// button here, so the top chrome is identical regardless of how
// this screen was reached. Backing out is still the system
// back gesture/button, same as any other pushed screen.
actions: const [MoreTabsButton(), ProfileAvatarButton()],
// Same trailing actions as every other tab except "More tabs" -
// there's nowhere useful for it to go while mid-upload (jumping to
// Trash/Shares/etc. would abandon this destination picker), so the
// top chrome is identical to every other tab minus that one entry.
// Backing out is still the system back gesture/button, same as any
// other pushed screen.
actions: const [ProfileAvatarButton()],
contentSlivers: contentSlivers,
),
// A rounded-top, elevated bar "peeking" up from the bottom edge - the