mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-13 01:10:31 -07:00
fix: padding issues (#47)
## Pull Request Description This fixes a bunch of padding issues, and also improves padding in other areas. Issue Number: #29 --------- Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
f5343be4e7
commit
6669a06e53
18 changed files with 926 additions and 877 deletions
|
|
@ -13,6 +13,7 @@ import 'package:fladder/screens/shared/focused_outlined_text_field.dart';
|
|||
import 'package:fladder/screens/shared/media/external_urls.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/util/string_extensions.dart';
|
||||
import 'package:fladder/widgets/shared/alert_content.dart';
|
||||
|
||||
Future<void> showIdentifyScreen(BuildContext context, ItemBaseModel item) async {
|
||||
return showDialogAdaptive(
|
||||
|
|
@ -50,215 +51,181 @@ class _IdentifyScreenState extends ConsumerState<IdentifyScreen> with TickerProv
|
|||
final state = ref.watch(provider);
|
||||
final posters = state.results;
|
||||
final processing = state.processing;
|
||||
return MediaQuery.removePadding(
|
||||
context: context,
|
||||
child: Card(
|
||||
return ActionContent(
|
||||
showDividers: false,
|
||||
title: Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: MediaQuery.paddingOf(context).top),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
widget.item.detailedName(context) ?? widget.item.name,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const Spacer(),
|
||||
IconButton(
|
||||
onPressed: () async => await ref.read(provider.notifier).fetchInformation(),
|
||||
icon: const Icon(IconsaxOutline.refresh)),
|
||||
],
|
||||
),
|
||||
),
|
||||
TabBar(
|
||||
isScrollable: true,
|
||||
controller: tabController,
|
||||
onTap: (value) {
|
||||
setState(() {
|
||||
currentTab = value;
|
||||
});
|
||||
},
|
||||
tabs: [
|
||||
Tab(
|
||||
text: context.localized.search,
|
||||
),
|
||||
Tab(
|
||||
text: context.localized.result,
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: TabBarView(
|
||||
controller: tabController,
|
||||
children: [
|
||||
inputFields(state),
|
||||
if (posters.isEmpty)
|
||||
Center(
|
||||
child: processing
|
||||
? const CircularProgressIndicator.adaptive(strokeCap: StrokeCap.round)
|
||||
: Text(context.localized.noResults),
|
||||
)
|
||||
else
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(context.localized.replaceAllImages),
|
||||
const SizedBox(width: 16),
|
||||
Switch.adaptive(
|
||||
value: state.replaceAllImages,
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(provider.notifier)
|
||||
.update((state) => state.copyWith(replaceAllImages: value));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Flexible(
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
children: posters
|
||||
.map((result) => ListTile(
|
||||
title: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 75,
|
||||
child: Card(
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: result.imageUrl ?? "",
|
||||
errorWidget: (context, url, error) => SizedBox(
|
||||
height: 75,
|
||||
child: Card(
|
||||
child: Center(
|
||||
child: Text(result.name?.getInitials() ?? ""),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${result.name ?? ""}${result.productionYear != null ? "(${result.productionYear})" : ""}"),
|
||||
Opacity(
|
||||
opacity: 0.65,
|
||||
child: Text(result.providerIds?.keys.join(',') ?? ""))
|
||||
],
|
||||
),
|
||||
),
|
||||
Tooltip(
|
||||
message: context.localized.openWebLink,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
final providerKeyEntry = result.providerIds?.entries.first;
|
||||
final providerKey = providerKeyEntry?.key;
|
||||
final providerValue = providerKeyEntry?.value;
|
||||
|
||||
final externalId = state.externalIds
|
||||
.firstWhereOrNull((element) => element.key == providerKey)
|
||||
?.urlFormatString;
|
||||
|
||||
final url =
|
||||
externalId?.replaceAll("{0}", providerValue?.toString() ?? "");
|
||||
|
||||
launchUrl(context, url ?? "");
|
||||
},
|
||||
icon: const Icon(Icons.launch_rounded)),
|
||||
),
|
||||
Tooltip(
|
||||
message: "Select result",
|
||||
child: IconButton(
|
||||
onPressed: !processing
|
||||
? () async {
|
||||
final response =
|
||||
await ref.read(provider.notifier).setIdentity(result);
|
||||
if (response?.isSuccessful == true) {
|
||||
fladderSnackbar(context,
|
||||
title:
|
||||
context.localized.setIdentityTo(result.name ?? ""));
|
||||
} else {
|
||||
fladderSnackbarResponse(context, response,
|
||||
altTitle: context.localized.somethingWentWrong);
|
||||
}
|
||||
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
: null,
|
||||
icon: const Icon(Icons.save_alt_rounded),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
widget.item.detailedName(context) ?? widget.item.name,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
IconButton(
|
||||
onPressed: () async => await ref.read(provider.notifier).fetchInformation(),
|
||||
icon: const Icon(IconsaxOutline.refresh)),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(onPressed: () => Navigator.of(context).pop(), child: Text(context.localized.cancel)),
|
||||
const SizedBox(width: 16),
|
||||
FilledButton(
|
||||
onPressed: !processing
|
||||
? () async {
|
||||
await ref.read(provider.notifier).remoteSearch();
|
||||
tabController.animateTo(1);
|
||||
}
|
||||
: null,
|
||||
child: processing
|
||||
? SizedBox(
|
||||
width: 21,
|
||||
height: 21,
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
backgroundColor: Theme.of(context).colorScheme.onPrimary, strokeCap: StrokeCap.round),
|
||||
)
|
||||
: Text(context.localized.search),
|
||||
),
|
||||
SizedBox(height: MediaQuery.paddingOf(context).bottom),
|
||||
],
|
||||
TabBar(
|
||||
isScrollable: true,
|
||||
controller: tabController,
|
||||
onTap: (value) {
|
||||
setState(() {
|
||||
currentTab = value;
|
||||
});
|
||||
},
|
||||
tabs: [
|
||||
Tab(
|
||||
text: context.localized.search,
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
text: context.localized.result,
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
child: TabBarView(
|
||||
controller: tabController,
|
||||
children: [
|
||||
inputFields(state),
|
||||
if (posters.isEmpty)
|
||||
Center(
|
||||
child: processing
|
||||
? const CircularProgressIndicator.adaptive(strokeCap: StrokeCap.round)
|
||||
: Text(context.localized.noResults),
|
||||
)
|
||||
else
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(context.localized.replaceAllImages),
|
||||
const SizedBox(width: 16),
|
||||
Switch.adaptive(
|
||||
value: state.replaceAllImages,
|
||||
onChanged: (value) {
|
||||
ref.read(provider.notifier).update((state) => state.copyWith(replaceAllImages: value));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Flexible(
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
children: posters
|
||||
.map((result) => ListTile(
|
||||
title: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 75,
|
||||
child: Card(
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: result.imageUrl ?? "",
|
||||
errorWidget: (context, url, error) => SizedBox(
|
||||
height: 75,
|
||||
child: Card(
|
||||
child: Center(
|
||||
child: Text(result.name?.getInitials() ?? ""),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${result.name ?? ""}${result.productionYear != null ? "(${result.productionYear})" : ""}"),
|
||||
Opacity(opacity: 0.65, child: Text(result.providerIds?.keys.join(',') ?? ""))
|
||||
],
|
||||
),
|
||||
),
|
||||
Tooltip(
|
||||
message: context.localized.openWebLink,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
final providerKeyEntry = result.providerIds?.entries.first;
|
||||
final providerKey = providerKeyEntry?.key;
|
||||
final providerValue = providerKeyEntry?.value;
|
||||
|
||||
final externalId = state.externalIds
|
||||
.firstWhereOrNull((element) => element.key == providerKey)
|
||||
?.urlFormatString;
|
||||
|
||||
final url = externalId?.replaceAll("{0}", providerValue?.toString() ?? "");
|
||||
|
||||
launchUrl(context, url ?? "");
|
||||
},
|
||||
icon: const Icon(Icons.launch_rounded)),
|
||||
),
|
||||
Tooltip(
|
||||
message: "Select result",
|
||||
child: IconButton(
|
||||
onPressed: !processing
|
||||
? () async {
|
||||
final response = await ref.read(provider.notifier).setIdentity(result);
|
||||
if (response?.isSuccessful == true) {
|
||||
fladderSnackbar(context,
|
||||
title: context.localized.setIdentityTo(result.name ?? ""));
|
||||
} else {
|
||||
fladderSnackbarResponse(context, response,
|
||||
altTitle: context.localized.somethingWentWrong);
|
||||
}
|
||||
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
: null,
|
||||
icon: const Icon(Icons.save_alt_rounded),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
ElevatedButton(onPressed: () => Navigator.of(context).pop(), child: Text(context.localized.cancel)),
|
||||
const SizedBox(width: 16),
|
||||
FilledButton(
|
||||
onPressed: !processing
|
||||
? () async {
|
||||
await ref.read(provider.notifier).remoteSearch();
|
||||
tabController.animateTo(1);
|
||||
}
|
||||
: null,
|
||||
child: processing
|
||||
? SizedBox(
|
||||
width: 21,
|
||||
height: 21,
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
backgroundColor: Theme.of(context).colorScheme.onPrimary, strokeCap: StrokeCap.round),
|
||||
)
|
||||
: Text(context.localized.search),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
ListView inputFields(IdentifyModel state) {
|
||||
return ListView(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'package:fladder/jellyfin/enum_models.dart';
|
||||
import 'package:fladder/providers/user_provider.dart';
|
||||
import 'package:fladder/screens/settings/settings_list_tile.dart';
|
||||
|
|
@ -5,8 +9,6 @@ import 'package:fladder/screens/shared/fladder_snackbar.dart';
|
|||
import 'package:fladder/util/adaptive_layout.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/widgets/shared/enum_selection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
Future<void> showRefreshPopup(BuildContext context, String itemId, String itemName) async {
|
||||
return showDialog(
|
||||
|
|
@ -60,18 +62,22 @@ class _RefreshPopupDialogState extends ConsumerState<RefreshPopupDialog> {
|
|||
),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
const SizedBox(height: 16),
|
||||
EnumBox(
|
||||
current: refreshMode.label(context),
|
||||
itemBuilder: (context) => MetadataRefresh.values
|
||||
.map((value) => PopupMenuItem(
|
||||
value: value,
|
||||
child: Text(value.label(context)),
|
||||
onTap: () => setState(() {
|
||||
refreshMode = value;
|
||||
}),
|
||||
))
|
||||
.toList(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: EnumBox(
|
||||
current: refreshMode.label(context),
|
||||
itemBuilder: (context) => MetadataRefresh.values
|
||||
.map((value) => PopupMenuItem(
|
||||
value: value,
|
||||
child: Text(value.label(context)),
|
||||
onTap: () => setState(() {
|
||||
refreshMode = value;
|
||||
}),
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
if (refreshMode != MetadataRefresh.defaultRefresh)
|
||||
SettingsListTile(
|
||||
|
|
@ -87,7 +93,7 @@ class _RefreshPopupDialogState extends ConsumerState<RefreshPopupDialog> {
|
|||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Divider(),
|
||||
Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Padding(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue