2024-02-02 07:48:20 +00:00
|
|
|
import 'dart:io';
|
|
|
|
|
2024-01-06 19:39:07 +00:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
2024-02-02 07:48:20 +00:00
|
|
|
import 'package:path/path.dart' as path;
|
2024-01-06 19:39:07 +00:00
|
|
|
|
|
|
|
import '../config.dart';
|
2024-02-02 07:48:20 +00:00
|
|
|
import '../controllers/filesharing.dart';
|
2024-01-06 19:39:07 +00:00
|
|
|
import '../cwtch_icons_icons.dart';
|
2024-02-02 07:48:20 +00:00
|
|
|
import '../main.dart';
|
|
|
|
import '../models/appstate.dart';
|
2024-01-06 19:39:07 +00:00
|
|
|
import '../settings.dart';
|
|
|
|
import '../themes/cwtch.dart';
|
|
|
|
import '../themes/opaque.dart';
|
2024-02-02 07:48:20 +00:00
|
|
|
import '../themes/yamltheme.dart';
|
2024-01-06 19:39:07 +00:00
|
|
|
import 'globalsettingsview.dart';
|
|
|
|
|
|
|
|
class GlobalSettingsAppearanceView extends StatefulWidget {
|
|
|
|
@override
|
|
|
|
_GlobalSettingsAppearanceViewState createState() => _GlobalSettingsAppearanceViewState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _GlobalSettingsAppearanceViewState extends State<GlobalSettingsAppearanceView> {
|
|
|
|
ScrollController settingsListScrollController = ScrollController();
|
|
|
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Consumer<Settings>(builder: (ccontext, settings, child) {
|
2024-02-03 02:08:21 +00:00
|
|
|
return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) {
|
|
|
|
return Scrollbar(
|
|
|
|
key: Key("AppearanceSettingsView"),
|
|
|
|
trackVisibility: true,
|
|
|
|
controller: settingsListScrollController,
|
|
|
|
child: SingleChildScrollView(
|
|
|
|
clipBehavior: Clip.antiAlias,
|
2024-01-06 19:39:07 +00:00
|
|
|
controller: settingsListScrollController,
|
2024-02-03 02:08:21 +00:00
|
|
|
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 20),
|
|
|
|
child: ConstrainedBox(
|
|
|
|
constraints: BoxConstraints(
|
|
|
|
minHeight: viewportConstraints.maxHeight,
|
|
|
|
),
|
|
|
|
child: Column(children: [
|
|
|
|
ListTile(
|
|
|
|
title: Text(AppLocalizations.of(context)!.settingLanguage),
|
|
|
|
leading: Icon(CwtchIcons.change_language, color: settings.current().mainTextColor),
|
|
|
|
trailing: Container(
|
|
|
|
width: MediaQuery.of(context).size.width / 4,
|
|
|
|
child: DropdownButton(
|
|
|
|
key: Key("languagelist"),
|
|
|
|
isExpanded: true,
|
|
|
|
value: Provider.of<Settings>(context).locale.toString(),
|
|
|
|
onChanged: (String? newValue) {
|
|
|
|
setState(() {
|
|
|
|
EnvironmentConfig.debugLog("setting language: $newValue");
|
|
|
|
settings.switchLocaleByCode(newValue!);
|
|
|
|
saveSettings(context);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
items: AppLocalizations.supportedLocales.map<DropdownMenuItem<String>>((Locale value) {
|
|
|
|
return DropdownMenuItem<String>(
|
|
|
|
value: value.toString(),
|
|
|
|
child: Text(
|
|
|
|
key: Key("dropdownLanguage" + value.languageCode),
|
|
|
|
getLanguageFull(context, value.languageCode, value.countryCode),
|
|
|
|
style: settings.scaleFonts(defaultDropDownMenuItemTextStyle),
|
|
|
|
overflow: TextOverflow.ellipsis,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}).toList()))),
|
|
|
|
SwitchListTile(
|
|
|
|
title: Text(AppLocalizations.of(context)!.settingTheme),
|
|
|
|
value: settings.current().mode == mode_light,
|
|
|
|
onChanged: (bool value) {
|
|
|
|
if (value) {
|
|
|
|
settings.setTheme(settings.theme.theme, mode_light);
|
|
|
|
} else {
|
|
|
|
settings.setTheme(settings.theme.theme, mode_dark);
|
|
|
|
}
|
2024-01-06 19:39:07 +00:00
|
|
|
|
|
|
|
// Save Settings...
|
2024-02-03 02:08:21 +00:00
|
|
|
saveSettings(context);
|
|
|
|
},
|
|
|
|
activeTrackColor: settings.theme.defaultButtonColor,
|
|
|
|
inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
|
|
|
|
secondary: Icon(CwtchIcons.change_theme, color: settings.current().mainTextColor),
|
|
|
|
),
|
|
|
|
ListTile(
|
|
|
|
title: Text(AppLocalizations.of(context)!.themeColorLabel),
|
|
|
|
trailing: Container(
|
|
|
|
width: MediaQuery.of(context).size.width / 4,
|
|
|
|
child: DropdownButton<String>(
|
|
|
|
key: Key("DropdownTheme"),
|
|
|
|
isExpanded: true,
|
2024-02-14 02:24:39 +00:00
|
|
|
value: Provider.of<Settings>(context).themeId,
|
2024-02-03 02:08:21 +00:00
|
|
|
onChanged: (String? newValue) {
|
|
|
|
setState(() {
|
2024-02-02 07:48:20 +00:00
|
|
|
settings.setTheme(newValue!, settings.theme.mode);
|
|
|
|
saveSettings(context);
|
|
|
|
});
|
|
|
|
},
|
2024-02-14 01:00:47 +00:00
|
|
|
items: settings.themeloader.themes.keys.map<DropdownMenuItem<String>>((String themeId) {
|
2024-02-02 07:48:20 +00:00
|
|
|
return DropdownMenuItem<String>(
|
|
|
|
value: themeId,
|
2024-02-14 02:24:39 +00:00
|
|
|
child: Text(getThemeName(context, settings, themeId), style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)), //"ddi_$themeId", key: Key("ddi_$themeId")),
|
2024-02-02 07:48:20 +00:00
|
|
|
);
|
|
|
|
}).toList())),
|
|
|
|
leading: Icon(Icons.palette, color: settings.current().mainTextColor),
|
|
|
|
),
|
2024-02-03 02:08:21 +00:00
|
|
|
Visibility(
|
|
|
|
// TODO: Android support needs gomobile support for reading / writing themes, and ideally importing from a .zip or .tar.gz
|
|
|
|
visible: !Platform.isAndroid,
|
|
|
|
child: ListTile(
|
|
|
|
leading: Icon(Icons.palette, color: Provider.of<Settings>(context).theme.messageFromMeTextColor),
|
|
|
|
title: Text(AppLocalizations.of(context)!.settingsImportThemeTitle),
|
|
|
|
subtitle: Text(AppLocalizations.of(context)!.settingsImportThemeDescription),
|
|
|
|
//AppLocalizations.of(
|
|
|
|
//context)!
|
|
|
|
//.fileSharingSettingsDownloadFolderDescription,
|
|
|
|
trailing: Container(
|
|
|
|
width: MediaQuery.of(context).size.width / 4,
|
|
|
|
child: ElevatedButton.icon(
|
|
|
|
label: Text(AppLocalizations.of(context)!.settingsImportThemeButton),
|
|
|
|
onPressed: Provider.of<AppState>(context).disableFilePicker
|
|
|
|
? null
|
|
|
|
: () async {
|
|
|
|
if (Platform.isAndroid) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var selectedDirectory = await showSelectDirectoryPicker(context);
|
|
|
|
if (selectedDirectory != null) {
|
|
|
|
selectedDirectory += path.separator;
|
|
|
|
final customThemeDir = path.join(await Provider.of<FlwtchState>(context, listen: false).cwtch.getCwtchDir(), custom_themes_subdir);
|
|
|
|
importThemeCheck(context, settings, customThemeDir, selectedDirectory);
|
|
|
|
} else {
|
|
|
|
// User canceled the picker
|
|
|
|
}
|
|
|
|
},
|
|
|
|
//onChanged: widget.onSave,
|
|
|
|
icon: Icon(Icons.folder),
|
|
|
|
//tooltip: widget.tooltip,
|
|
|
|
)))),
|
2024-02-02 07:48:20 +00:00
|
|
|
SwitchListTile(
|
|
|
|
title: Text(AppLocalizations.of(context)!.settingsThemeImages),
|
|
|
|
subtitle: Text(AppLocalizations.of(context)!.settingsThemeImagesDescription),
|
|
|
|
value: settings.themeImages,
|
|
|
|
onChanged: (bool value) {
|
|
|
|
settings.themeImages = value; // Save Settings...
|
|
|
|
saveSettings(context);
|
|
|
|
},
|
|
|
|
activeTrackColor: settings.theme.defaultButtonColor,
|
|
|
|
inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
|
|
|
|
secondary: Icon(Icons.image, color: settings.current().mainTextColor),
|
|
|
|
),
|
|
|
|
ListTile(
|
|
|
|
title: Text(AppLocalizations.of(context)!.settingUIColumnPortrait),
|
2024-02-03 02:08:21 +00:00
|
|
|
leading: Icon(Icons.table_chart, color: settings.current().mainTextColor),
|
|
|
|
trailing: Container(
|
|
|
|
width: MediaQuery.of(context).size.width / 4,
|
|
|
|
child: DropdownButton(
|
|
|
|
isExpanded: true,
|
|
|
|
value: settings.uiColumnModePortrait.toString(),
|
|
|
|
onChanged: (String? newValue) {
|
|
|
|
settings.uiColumnModePortrait = Settings.uiColumnModeFromString(newValue!);
|
|
|
|
saveSettings(context);
|
|
|
|
},
|
|
|
|
items: Settings.uiColumnModeOptions(false).map<DropdownMenuItem<String>>((DualpaneMode value) {
|
|
|
|
return DropdownMenuItem<String>(
|
|
|
|
value: value.toString(),
|
|
|
|
child: Text(Settings.uiColumnModeToString(value, context), style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
|
|
|
|
);
|
|
|
|
}).toList()))),
|
|
|
|
ListTile(
|
|
|
|
title: Text(
|
|
|
|
AppLocalizations.of(context)!.settingUIColumnLandscape,
|
|
|
|
textWidthBasis: TextWidthBasis.longestLine,
|
|
|
|
softWrap: true,
|
|
|
|
),
|
|
|
|
leading: Icon(Icons.stay_primary_landscape, color: settings.current().mainTextColor),
|
|
|
|
trailing: Container(
|
|
|
|
width: MediaQuery.of(context).size.width / 4,
|
|
|
|
child: Container(
|
|
|
|
width: MediaQuery.of(context).size.width / 4,
|
2024-01-06 19:39:07 +00:00
|
|
|
child: DropdownButton(
|
|
|
|
isExpanded: true,
|
2024-02-03 02:08:21 +00:00
|
|
|
value: settings.uiColumnModeLandscape.toString(),
|
2024-01-06 19:39:07 +00:00
|
|
|
onChanged: (String? newValue) {
|
2024-02-03 02:08:21 +00:00
|
|
|
settings.uiColumnModeLandscape = Settings.uiColumnModeFromString(newValue!);
|
2024-01-06 19:39:07 +00:00
|
|
|
saveSettings(context);
|
|
|
|
},
|
2024-02-03 02:08:21 +00:00
|
|
|
items: Settings.uiColumnModeOptions(true).map<DropdownMenuItem<String>>((DualpaneMode value) {
|
|
|
|
return DropdownMenuItem<String>(
|
|
|
|
value: value.toString(),
|
|
|
|
child: Text(Settings.uiColumnModeToString(value, context), overflow: TextOverflow.ellipsis, style: settings.scaleFonts(defaultDropDownMenuItemTextStyle)),
|
|
|
|
);
|
|
|
|
}).toList())))),
|
|
|
|
ListTile(
|
|
|
|
title: Text(AppLocalizations.of(context)!.defaultScalingText),
|
|
|
|
subtitle: Text(AppLocalizations.of(context)!.fontScalingDescription),
|
|
|
|
trailing: Container(
|
|
|
|
width: MediaQuery.of(context).size.width / 4,
|
|
|
|
child: Slider(
|
|
|
|
onChanged: (double value) {
|
|
|
|
settings.fontScaling = value;
|
2024-01-06 19:39:07 +00:00
|
|
|
// Save Settings...
|
2024-02-03 02:08:21 +00:00
|
|
|
saveSettings(context);
|
|
|
|
EnvironmentConfig.debugLog("Font Scaling: $value");
|
|
|
|
},
|
|
|
|
min: 0.5,
|
|
|
|
divisions: 12,
|
|
|
|
max: 2.0,
|
|
|
|
label: '${settings.fontScaling * 100}%',
|
|
|
|
activeColor: settings.current().defaultButtonColor,
|
|
|
|
thumbColor: settings.current().mainTextColor,
|
|
|
|
overlayColor: MaterialStateProperty.all(settings.current().mainTextColor),
|
|
|
|
inactiveColor: settings.theme.defaultButtonDisabledColor,
|
|
|
|
value: settings.fontScaling)),
|
|
|
|
leading: Icon(Icons.format_size, color: settings.current().mainTextColor),
|
|
|
|
),
|
|
|
|
SwitchListTile(
|
|
|
|
title: Text(AppLocalizations.of(context)!.streamerModeLabel),
|
|
|
|
subtitle: Text(AppLocalizations.of(context)!.descriptionStreamerMode),
|
|
|
|
value: settings.streamerMode,
|
|
|
|
onChanged: (bool value) {
|
|
|
|
settings.setStreamerMode(value);
|
2024-01-06 19:39:07 +00:00
|
|
|
// Save Settings...
|
2024-02-03 02:08:21 +00:00
|
|
|
saveSettings(context);
|
|
|
|
},
|
|
|
|
activeTrackColor: settings.theme.defaultButtonColor,
|
|
|
|
inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
|
|
|
|
secondary: Icon(CwtchIcons.streamer_bunnymask, color: settings.current().mainTextColor),
|
|
|
|
),
|
|
|
|
SwitchListTile(
|
|
|
|
title: Text(AppLocalizations.of(context)!.formattingExperiment),
|
|
|
|
subtitle: Text(AppLocalizations.of(context)!.messageFormattingDescription),
|
|
|
|
value: settings.isExperimentEnabled(FormattingExperiment),
|
|
|
|
onChanged: (bool value) {
|
|
|
|
if (value) {
|
|
|
|
settings.enableExperiment(FormattingExperiment);
|
|
|
|
} else {
|
|
|
|
settings.disableExperiment(FormattingExperiment);
|
|
|
|
}
|
|
|
|
saveSettings(context);
|
|
|
|
},
|
|
|
|
activeTrackColor: settings.theme.defaultButtonActiveColor,
|
|
|
|
inactiveTrackColor: settings.theme.defaultButtonDisabledColor,
|
|
|
|
secondary: Icon(Icons.text_fields, color: settings.current().mainTextColor),
|
|
|
|
),
|
|
|
|
]))));
|
|
|
|
});
|
2024-01-06 19:39:07 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A slightly verbose way to extract the full language name from
|
|
|
|
/// an individual language code. There might be a more efficient way of doing this.
|
|
|
|
String getLanguageFull(context, String languageCode, String? countryCode) {
|
|
|
|
if (languageCode == "en") {
|
|
|
|
return AppLocalizations.of(context)!.localeEn;
|
|
|
|
}
|
|
|
|
if (languageCode == "es") {
|
|
|
|
return AppLocalizations.of(context)!.localeEs;
|
|
|
|
}
|
|
|
|
if (languageCode == "fr") {
|
|
|
|
return AppLocalizations.of(context)!.localeFr;
|
|
|
|
}
|
|
|
|
if (languageCode == "pt" && countryCode == "BR") {
|
|
|
|
return AppLocalizations.of(context)!.localePtBr;
|
|
|
|
}
|
|
|
|
if (languageCode == "pt") {
|
|
|
|
return AppLocalizations.of(context)!.localePt;
|
|
|
|
}
|
|
|
|
if (languageCode == "de") {
|
|
|
|
return AppLocalizations.of(context)!.localeDe;
|
|
|
|
}
|
|
|
|
if (languageCode == "el") {
|
|
|
|
return AppLocalizations.of(context)!.localeEl;
|
|
|
|
}
|
|
|
|
if (languageCode == "it") {
|
|
|
|
return AppLocalizations.of(context)!.localeIt;
|
|
|
|
}
|
|
|
|
if (languageCode == "no") {
|
|
|
|
return AppLocalizations.of(context)!.localeNo;
|
|
|
|
}
|
|
|
|
if (languageCode == "pl") {
|
|
|
|
return AppLocalizations.of(context)!.localePl;
|
|
|
|
}
|
|
|
|
if (languageCode == "lb") {
|
|
|
|
return AppLocalizations.of(context)!.localeLb;
|
|
|
|
}
|
|
|
|
if (languageCode == "ru") {
|
|
|
|
return AppLocalizations.of(context)!.localeRU;
|
|
|
|
}
|
|
|
|
if (languageCode == "ro") {
|
|
|
|
return AppLocalizations.of(context)!.localeRo;
|
|
|
|
}
|
|
|
|
if (languageCode == "cy") {
|
|
|
|
return AppLocalizations.of(context)!.localeCy;
|
|
|
|
}
|
|
|
|
if (languageCode == "da") {
|
|
|
|
return AppLocalizations.of(context)!.localeDa;
|
|
|
|
}
|
|
|
|
if (languageCode == "tr") {
|
|
|
|
return AppLocalizations.of(context)!.localeTr;
|
|
|
|
}
|
|
|
|
if (languageCode == "nl") {
|
|
|
|
return AppLocalizations.of(context)!.localeNl;
|
|
|
|
}
|
|
|
|
if (languageCode == "sk") {
|
|
|
|
return AppLocalizations.of(context)!.localeSk;
|
|
|
|
}
|
|
|
|
if (languageCode == "ko") {
|
|
|
|
return AppLocalizations.of(context)!.localeKo;
|
|
|
|
}
|
|
|
|
if (languageCode == "ja") {
|
|
|
|
return AppLocalizations.of(context)!.localeJa;
|
|
|
|
}
|
|
|
|
if (languageCode == "sv") {
|
|
|
|
return AppLocalizations.of(context)!.localeSv;
|
|
|
|
}
|
|
|
|
if (languageCode == "sw") {
|
|
|
|
return AppLocalizations.of(context)!.localeSw;
|
|
|
|
}
|
|
|
|
if (languageCode == "uk") {
|
|
|
|
return AppLocalizations.of(context)!.localeUk;
|
|
|
|
}
|
|
|
|
if (languageCode == "uz") {
|
|
|
|
return AppLocalizations.of(context)!.localeUzbek;
|
|
|
|
}
|
|
|
|
return languageCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Since we don't seem to able to dynamically pull translations, this function maps themes to their names
|
2024-02-14 02:24:39 +00:00
|
|
|
String getThemeName(context, Settings settings, String theme) {
|
2024-01-06 19:39:07 +00:00
|
|
|
switch (theme) {
|
|
|
|
case cwtch_theme:
|
|
|
|
return AppLocalizations.of(context)!.themeNameCwtch;
|
|
|
|
case "ghost":
|
|
|
|
return AppLocalizations.of(context)!.themeNameGhost;
|
|
|
|
case "mermaid":
|
|
|
|
return AppLocalizations.of(context)!.themeNameMermaid;
|
|
|
|
case "midnight":
|
|
|
|
return AppLocalizations.of(context)!.themeNameMidnight;
|
|
|
|
case "neon1":
|
|
|
|
return AppLocalizations.of(context)!.themeNameNeon1;
|
|
|
|
case "neon2":
|
|
|
|
return AppLocalizations.of(context)!.themeNameNeon2;
|
|
|
|
case "pumpkin":
|
|
|
|
return AppLocalizations.of(context)!.themeNamePumpkin;
|
|
|
|
case "vampire":
|
|
|
|
return AppLocalizations.of(context)!.themeNameVampire;
|
|
|
|
case "witch":
|
|
|
|
return AppLocalizations.of(context)!.themeNameWitch;
|
|
|
|
case "juniper":
|
|
|
|
return "Juniper"; // Juniper is a noun, and doesn't get subject to translation...
|
|
|
|
}
|
2024-02-14 02:24:39 +00:00
|
|
|
return settings.themeloader.themes[theme]?[settings.theme.mode]?.theme ?? theme;
|
2024-01-06 19:39:07 +00:00
|
|
|
}
|
2024-02-02 07:48:20 +00:00
|
|
|
|
|
|
|
void importThemeCheck(BuildContext context, Settings settings, String themesDir, String newThemeDirectory) async {
|
|
|
|
// check is theme
|
|
|
|
final srcDir = Directory(newThemeDirectory);
|
|
|
|
String themeName = path.basename(newThemeDirectory);
|
|
|
|
|
|
|
|
File themeFile = File(path.join(newThemeDirectory, "theme.yml"));
|
|
|
|
|
|
|
|
if (!themeFile.existsSync()) {
|
|
|
|
// error, isnt valid theme, no .yml theme file found
|
|
|
|
SnackBar err = SnackBar(content: Text(AppLocalizations.of(context)!.settingsThemeErrorInvalid.replaceAll("\$themeName", themeName)));
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Directory targetDir = Directory(path.join(themesDir, themeName));
|
|
|
|
// check if exists
|
2024-02-14 01:00:47 +00:00
|
|
|
if (settings.themeloader.themes.containsKey(themeName) || targetDir.existsSync()) {
|
2024-02-02 07:48:20 +00:00
|
|
|
_modalConfirmOverwriteCustomTheme(srcDir, targetDir, themesDir, themeName, settings);
|
|
|
|
} else {
|
|
|
|
importTheme(srcDir, targetDir, themesDir, themeName, settings);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void importTheme(Directory srcDir, Directory targetDir, String themesDir, String themeName, Settings settings) async {
|
|
|
|
if (!targetDir.existsSync()) {
|
|
|
|
targetDir = await targetDir.create();
|
|
|
|
}
|
|
|
|
|
|
|
|
// importTheme(newVal)
|
|
|
|
await for (var entity in srcDir.list(recursive: false)) {
|
|
|
|
if (entity is File) {
|
|
|
|
entity.copySync(path.join(targetDir.path, path.basename(entity.path)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var data = await loadFileYamlTheme(path.join(targetDir.path, "theme.yml"), targetDir.path);
|
|
|
|
if (data != null) {
|
2024-02-14 01:00:47 +00:00
|
|
|
settings.themeloader.themes[themeName] = data;
|
2024-02-02 07:48:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (settings.current().theme == themeName) {
|
|
|
|
settings.setTheme(themeName, settings.current().mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void _modalConfirmOverwriteCustomTheme(Directory srcDir, Directory targetDir, String themesDir, String themeName, Settings settings) {
|
|
|
|
showModalBottomSheet<void>(
|
|
|
|
context: context,
|
|
|
|
isScrollControlled: true,
|
|
|
|
builder: (BuildContext context) {
|
|
|
|
return Padding(
|
|
|
|
padding: MediaQuery.of(context).viewInsets,
|
|
|
|
child: RepaintBoundary(
|
|
|
|
child: Container(
|
|
|
|
height: Platform.isAndroid ? 250 : 200, // bespoke value courtesy of the [TextField] docs
|
|
|
|
child: Center(
|
|
|
|
child: Padding(
|
|
|
|
padding: EdgeInsets.all(10.0),
|
|
|
|
child: Column(mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: <Widget>[
|
|
|
|
Text(AppLocalizations.of(context)!.settingThemeOverwriteQuestion.replaceAll("\$themeName", themeName)),
|
|
|
|
SizedBox(
|
|
|
|
height: 20,
|
|
|
|
),
|
|
|
|
Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
|
|
children: [
|
|
|
|
Spacer(),
|
|
|
|
Expanded(
|
|
|
|
child: ElevatedButton(
|
|
|
|
child: Text(AppLocalizations.of(context)!.settingThemeOverwriteConfirm, semanticsLabel: AppLocalizations.of(context)!.settingThemeOverwriteConfirm),
|
|
|
|
onPressed: () {
|
|
|
|
importTheme(srcDir, targetDir, themesDir, themeName, settings);
|
|
|
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
},
|
|
|
|
)),
|
|
|
|
SizedBox(
|
|
|
|
width: 20,
|
|
|
|
),
|
|
|
|
Expanded(
|
|
|
|
child: ElevatedButton(
|
|
|
|
child: Text(AppLocalizations.of(context)!.cancel, semanticsLabel: AppLocalizations.of(context)!.cancel),
|
|
|
|
onPressed: () {
|
|
|
|
Navigator.pop(context);
|
|
|
|
},
|
|
|
|
)),
|
|
|
|
Spacer(),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
]))))));
|
|
|
|
});
|
|
|
|
}
|
2024-01-06 19:39:07 +00:00
|
|
|
}
|