Add custom background (#2442)

* Add ability to put a custom background to the home page

* add translation [skip ci]
This commit is contained in:
Omar Hatem
2025-08-09 14:30:55 +03:00
committed by GitHub
parent f556603392
commit ce1102187e
37 changed files with 162 additions and 20 deletions
+32 -9
View File
@@ -1,3 +1,6 @@
import 'dart:io';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/themes/core/material_base_theme.dart';
import 'package:cake_wallet/themes/core/theme_store.dart';
import 'package:cake_wallet/utils/route_aware.dart';
@@ -6,6 +9,7 @@ import 'package:flutter/material.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/src/widgets/nav_bar.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
enum AppBarStyle { regular, withShadow, transparent, completelyTransparent }
@@ -173,15 +177,34 @@ abstract class BasePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final root = RouteAwareWidget(
child: Scaffold(
key: _scaffoldKey,
backgroundColor: pageBackgroundColor(context),
resizeToAvoidBottomInset: resizeToAvoidBottomInset,
extendBodyBehindAppBar: extendBodyBehindAppBar,
endDrawer: endDrawer,
appBar: appBar(context),
body: body(context),
floatingActionButton: floatingActionButton(context)),
child: Observer(
builder: (context) {
final backgroundImage = getIt.get<SettingsStore>().backgroundImage;
return Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
image: backgroundImage.isNotEmpty
? DecorationImage(
image: FileImage(File(backgroundImage)),
fit: BoxFit.cover,
)
: null,
// color: Colors.grey[200],
),
child: Scaffold(
key: _scaffoldKey,
backgroundColor: pageBackgroundColor(context),
resizeToAvoidBottomInset: resizeToAvoidBottomInset,
extendBodyBehindAppBar: extendBodyBehindAppBar,
endDrawer: endDrawer,
appBar: appBar(context),
body: body(context),
floatingActionButton: floatingActionButton(context)),
);
}
),
pushToWidget: (context) => pushToWidget?.call(context),
pushToNextWidget: (context) => pushToNextWidget?.call(context),
popWidget: (context) => popWidget?.call(context),
@@ -24,13 +24,13 @@ class NavigationDock extends StatelessWidget {
return Container(
height: 150,
alignment: Alignment.bottomCenter,
decoration: BoxDecoration(
decoration: dashboardViewModel.settingsStore.backgroundImage.isEmpty ? BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: _getColors(context, !currentTheme.isDark),
),
),
) : null,
//color: Colors.transparent,
child: Container(
decoration: BoxDecoration(
@@ -41,7 +41,7 @@ class PresentReceiveOptionPicker extends StatelessWidget {
Text(
S.current.receive,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 18.0,
fontSize: 17.0,
fontWeight: FontWeight.bold,
color: color,
),
@@ -5,11 +5,15 @@ import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_theme_choice.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/src/widgets/standard_list.dart';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:image_picker/image_picker.dart';
class DisplaySettingsPage extends BasePage {
DisplaySettingsPage(this._displaySettingsViewModel);
@@ -28,7 +32,7 @@ class DisplaySettingsPage extends BasePage {
child: Column(
children: [
SettingsSwitcherCell(
title: S.current.show_market_place,
title: S.of(context).show_market_place,
value: _displaySettingsViewModel.shouldShowMarketPlaceInDashboard,
onValueChange: (_, bool value) {
_displaySettingsViewModel.setShouldShowMarketPlaceInDashbaord(value);
@@ -44,8 +48,8 @@ class DisplaySettingsPage extends BasePage {
//if (!isHaven) it does not work correctly
if (!_displaySettingsViewModel.disabledFiatApiMode)
SettingsPickerCell<FiatCurrency>(
title: S.current.settings_currency,
searchHintText: S.current.search_currency,
title: S.of(context).settings_currency,
searchHintText: S.of(context).search_currency,
items: FiatCurrency.all,
selectedItem: _displaySettingsViewModel.fiatCurrency,
onItemSelected: (FiatCurrency currency) =>
@@ -60,8 +64,8 @@ class DisplaySettingsPage extends BasePage {
},
),
SettingsPickerCell<String>(
title: S.current.settings_change_language,
searchHintText: S.current.search_language,
title: S.of(context).settings_change_language,
searchHintText: S.of(context).search_language,
items: LanguageService.list.keys.toList(),
displayItem: (dynamic code) {
return LanguageService.list[code] ?? '';
@@ -77,9 +81,15 @@ class DisplaySettingsPage extends BasePage {
},
),
StandardListRow(
title: "Custom background",
isSelected: false,
onTap: (_) => _pickImage(context),
),
if (responsiveLayoutUtil.shouldRenderMobileUI && DeviceInfo.instance.isMobile) ...[
SettingsSwitcherCell(
title: S.current.use_device_theme,
title: S.of(context).use_device_theme,
value: _displaySettingsViewModel.themeMode == ThemeMode.system,
onValueChange: (_, bool value) {
_displaySettingsViewModel
@@ -87,7 +97,7 @@ class DisplaySettingsPage extends BasePage {
},
),
Semantics(
label: S.current.color_theme,
label: S.of(context).color_theme,
child: SettingsThemeChoicesCell(_displaySettingsViewModel),
),
],
@@ -97,4 +107,38 @@ class DisplaySettingsPage extends BasePage {
}),
);
}
// Function to pick an image from the gallery
Future<void> _pickImage(BuildContext context) async {
if (_displaySettingsViewModel.backgroundImage.isNotEmpty) {
final bool? shouldReplace = await showPopUp<bool>(
context: context,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: S.of(context).replace,
alertContent: S.of(context).customBackgroundDescription,
rightButtonText: S.of(context).replace,
leftButtonText: S.of(context).remove,
actionRightButton: () => Navigator.of(context).pop(true),
actionLeftButton: () => Navigator.of(context).pop(false));
});
if (shouldReplace == false) {
// remove the current background by setting it as an empty string
_displaySettingsViewModel.setBackgroundImage("");
return;
} else if (shouldReplace == null) {
// user didn't choose anything, then just return
return;
}
}
final ImagePicker picker = ImagePicker();
// Pick an image from the gallery
final XFile? pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
_displaySettingsViewModel.setBackgroundImage(pickedFile.path);
}
}
}