various fixes, layout tweaks, and refactoring

This commit is contained in:
julian 2023-05-10 16:49:56 -06:00
parent 6ed6ffb18b
commit 6990d60b9b
4 changed files with 234 additions and 100 deletions

View file

@ -1645,7 +1645,9 @@ class StackTheme {
backgroundInt: parseColor(json["colors"]["background"] as String), backgroundInt: parseColor(json["colors"]["background"] as String),
backgroundAppBarInt: backgroundAppBarInt:
parseColor(json["colors"]["background_app_bar"] as String), parseColor(json["colors"]["background_app_bar"] as String),
gradientBackgroundString: json["colors"]["gradients"] as String?, gradientBackgroundString: json["colors"]["gradients"] != null
? jsonEncode(json["colors"]["gradients"])
: null,
standardBoxShadowString: standardBoxShadowString:
jsonEncode(json["colors"]["box_shadows"]["standard"] as Map), jsonEncode(json["colors"]["box_shadows"]["standard"] as Map),
homeViewButtonBarBoxShadowString: homeViewButtonBarBoxShadowString:

View file

@ -1,24 +1,25 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/stack_theme_card.dart';
import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_service.dart';
import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/rounded_container.dart'; import 'package:stackwallet/widgets/loading_indicator.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class ManageThemesView extends StatefulWidget { class ManageThemesView extends ConsumerStatefulWidget {
const ManageThemesView({Key? key}) : super(key: key); const ManageThemesView({Key? key}) : super(key: key);
static const String routeName = "/manageThemes"; static const String routeName = "/manageThemes";
@override @override
State<ManageThemesView> createState() => _ManageThemesViewState(); ConsumerState<ManageThemesView> createState() => _ManageThemesViewState();
} }
class _ManageThemesViewState extends State<ManageThemesView> { class _ManageThemesViewState extends ConsumerState<ManageThemesView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ConditionalParent( return ConditionalParent(
@ -36,105 +37,64 @@ class _ManageThemesViewState extends State<ManageThemesView> {
style: STextStyles.navBarTitle(context), style: STextStyles.navBarTitle(context),
), ),
), ),
body: SingleChildScrollView( body: Column(
child: Padding( children: [
padding: const EdgeInsets.symmetric( Expanded(
horizontal: 16, child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
),
child: IntrinsicHeight(
child: child,
),
),
),
), ),
child: child, Padding(
), padding: const EdgeInsets.all(16),
child: SecondaryButton(
label: "Install theme file",
onPressed: () {},
),
),
],
), ),
), ),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const SizedBox( FutureBuilder(
height: 16, future: ref.watch(pThemeService).fetchThemes(),
), builder: (
GridView.builder( context,
shrinkWrap: true, AsyncSnapshot<List<StackThemeMetaData>> snapshot,
primary: false, ) {
itemCount: 100, if (snapshot.connectionState == ConnectionState.done &&
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( snapshot.hasData) {
crossAxisCount: 2, return Wrap(
crossAxisSpacing: 16, spacing: 16,
mainAxisSpacing: 16, runSpacing: 16,
childAspectRatio: 2 / 2.7, children: snapshot.data!
), .map(
itemBuilder: (_, index) { (e) => SizedBox(
return StackThemeCard( width: (MediaQuery.of(context).size.width - 48) / 2,
name: index.toString(), child: StackThemeCard(
size: "lol GB", data: e,
); ),
),
)
.toList(),
);
} else {
return Center(
child: LoadingIndicator(
width: (MediaQuery.of(context).size.width - 48) / 2,
),
);
}
}, },
), ),
const SizedBox(
height: 28,
),
SecondaryButton(
label: "Install theme file",
onPressed: () {},
),
const SizedBox(
height: 16,
),
],
),
);
}
}
class StackThemeCard extends StatefulWidget {
const StackThemeCard({
Key? key,
required this.name,
required this.size,
}) : super(key: key);
final String name;
final String size;
@override
State<StackThemeCard> createState() => _StackThemeCardState();
}
class _StackThemeCardState extends State<StackThemeCard> {
String buttonLabel = "Download";
@override
Widget build(BuildContext context) {
return RoundedWhiteContainer(
child: Column(
children: [
const Padding(
padding: EdgeInsets.symmetric(
horizontal: 18,
),
child: AspectRatio(
aspectRatio: 1,
child: RoundedContainer(
color: Colors.grey,
radiusMultiplier: 100,
),
),
),
const SizedBox(
height: 12,
),
Text(
widget.name,
),
const SizedBox(
height: 6,
),
Text(
widget.size,
),
const Spacer(),
PrimaryButton(
label: buttonLabel,
buttonHeight: ButtonHeight.l,
onPressed: () {},
),
], ],
), ),
); );

View file

@ -0,0 +1,167 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/providers/db/main_db_provider.dart';
import 'package:stackwallet/themes/theme_service.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
class StackThemeCard extends ConsumerStatefulWidget {
const StackThemeCard({
Key? key,
required this.data,
}) : super(key: key);
final StackThemeMetaData data;
@override
ConsumerState<StackThemeCard> createState() => _StackThemeCardState();
}
class _StackThemeCardState extends ConsumerState<StackThemeCard> {
String buttonLabel = "Download";
late bool _hasTheme;
Future<bool> _downloadAndInstall() async {
final service = ref.read(pThemeService);
try {
final data = await service.fetchTheme(
themeMetaData: widget.data,
);
await service.install(themeArchive: data);
return true;
} catch (e, s) {
Logging.instance.log(
"Failed _downloadAndInstall of ${widget.data.id}: $e\n$s",
level: LogLevel.Warning,
);
return false;
}
}
Future<void> _downloadPressed() async {
final result = await showLoading(
whileFuture: _downloadAndInstall(),
context: context,
message: "Downloading and installing theme...",
);
if (mounted) {
final message = result
? "${widget.data.name} theme installed!"
: "Failed to install ${widget.data.name} theme";
await showDialog<void>(
context: context,
builder: (_) => StackOkDialog(
title: message,
onOkPressed: (_) {
setState(() {
_hasTheme = result;
});
},
),
);
}
}
late final StreamSubscription<void> _subscription;
@override
void initState() {
_hasTheme = ref
.read(mainDBProvider)
.isar
.stackThemes
.where()
.themeIdEqualTo(widget.data.id)
.countSync() >
0;
_subscription = ref
.read(mainDBProvider)
.isar
.stackThemes
.watchLazy()
.listen((event) async {
final hasTheme = (await ref
.read(mainDBProvider)
.isar
.stackThemes
.where()
.themeIdEqualTo(widget.data.id)
.count()) >
0;
if (_hasTheme != hasTheme && mounted) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
_hasTheme = hasTheme;
});
});
}
});
_subscription.resume();
super.initState();
}
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return RoundedWhiteContainer(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 18,
),
child: AspectRatio(
aspectRatio: 1,
child: ClipRRect(
borderRadius: BorderRadius.circular(100),
child: Image.network(
widget.data.previewImageUrl,
),
),
),
),
const SizedBox(
height: 12,
),
Text(
widget.data.name,
),
const SizedBox(
height: 6,
),
Text(
widget.data.size,
),
const SizedBox(
height: 12,
),
PrimaryButton(
label: buttonLabel,
enabled: !_hasTheme,
buttonHeight: ButtonHeight.l,
onPressed: _downloadPressed,
),
],
),
);
}
}

View file

@ -117,7 +117,7 @@ class ThemeService {
} }
} }
Future<List<StackThemeMetaData>> fetchThemeList() async { Future<List<StackThemeMetaData>> fetchThemes() async {
try { try {
final response = await get(Uri.parse("$baseServerUrl/themes")); final response = await get(Uri.parse("$baseServerUrl/themes"));
@ -125,6 +125,7 @@ class ThemeService {
final result = List<Map<String, dynamic>>.from(jsonList) final result = List<Map<String, dynamic>>.from(jsonList)
.map((e) => StackThemeMetaData.fromMap(e)) .map((e) => StackThemeMetaData.fromMap(e))
.where((e) => e.id != "light" && e.id != "dark")
.toList(); .toList();
return result; return result;
@ -178,12 +179,14 @@ class StackThemeMetaData {
final String name; final String name;
final String id; final String id;
final String sha256; final String sha256;
final String size;
final String previewImageUrl; final String previewImageUrl;
StackThemeMetaData({ StackThemeMetaData({
required this.name, required this.name,
required this.id, required this.id,
required this.sha256, required this.sha256,
required this.size,
required this.previewImageUrl, required this.previewImageUrl,
}); });
@ -193,6 +196,7 @@ class StackThemeMetaData {
name: map["name"] as String, name: map["name"] as String,
id: map["id"] as String, id: map["id"] as String,
sha256: map["sha256"] as String, sha256: map["sha256"] as String,
size: map["size"] as String,
previewImageUrl: map["previewImageUrl"] as String, previewImageUrl: map["previewImageUrl"] as String,
); );
} catch (e, s) { } catch (e, s) {
@ -210,6 +214,7 @@ class StackThemeMetaData {
"name: $name, " "name: $name, "
"id: $id, " "id: $id, "
"sha256: $sha256, " "sha256: $sha256, "
"size: $size, "
"previewImageUrl: $previewImageUrl" "previewImageUrl: $previewImageUrl"
")"; ")";
} }