#203 info: copy date from other item

This commit is contained in:
Thibault Deckers 2022-03-18 17:06:27 +09:00
parent 318ee1385e
commit 150e94cee5
13 changed files with 174 additions and 47 deletions

View file

@ -335,6 +335,7 @@
"editEntryDateDialogTitle": "Date & Time", "editEntryDateDialogTitle": "Date & Time",
"editEntryDateDialogSetCustom": "Set custom date", "editEntryDateDialogSetCustom": "Set custom date",
"editEntryDateDialogCopyField": "Copy from other date", "editEntryDateDialogCopyField": "Copy from other date",
"editEntryDateDialogCopyItem": "Copy from other item",
"editEntryDateDialogExtractFromTitle": "Extract from title", "editEntryDateDialogExtractFromTitle": "Extract from title",
"editEntryDateDialogShift": "Shift", "editEntryDateDialogShift": "Shift",
"editEntryDateDialogSourceFileModifiedDate": "File modified date", "editEntryDateDialogSourceFileModifiedDate": "File modified date",

View file

@ -42,6 +42,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry {
switch (appliedModifier.action) { switch (appliedModifier.action) {
case DateEditAction.setCustom: case DateEditAction.setCustom:
case DateEditAction.copyField: case DateEditAction.copyField:
case DateEditAction.copyItem:
case DateEditAction.extractFromTitle: case DateEditAction.extractFromTitle:
editCreateDateXmp(descriptions, appliedModifier.setDateTime); editCreateDateXmp(descriptions, appliedModifier.setDateTime);
break; break;
@ -319,6 +320,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry {
final date = parseUnknownDateFormat(bestTitle); final date = parseUnknownDateFormat(bestTitle);
return date != null ? DateModifier.setCustom(mainMetadataDate(), date) : null; return date != null ? DateModifier.setCustom(mainMetadataDate(), date) : null;
case DateEditAction.setCustom: case DateEditAction.setCustom:
case DateEditAction.copyItem:
return DateModifier.setCustom(mainMetadataDate(), modifier.setDateTime!); return DateModifier.setCustom(mainMetadataDate(), modifier.setDateTime!);
case DateEditAction.shift: case DateEditAction.shift:
case DateEditAction.remove: case DateEditAction.remove:

View file

@ -24,30 +24,30 @@ class DateModifier extends Equatable {
List<Object?> get props => [action, fields, setDateTime, copyFieldSource, shiftMinutes]; List<Object?> get props => [action, fields, setDateTime, copyFieldSource, shiftMinutes];
const DateModifier._private( const DateModifier._private(
this.action, this.action, {
this.fields, { this.fields = const {},
this.setDateTime, this.setDateTime,
this.copyFieldSource, this.copyFieldSource,
this.shiftMinutes, this.shiftMinutes,
}); });
factory DateModifier.setCustom(Set<MetadataField> fields, DateTime dateTime) { factory DateModifier.setCustom(Set<MetadataField> fields, DateTime dateTime) {
return DateModifier._private(DateEditAction.setCustom, fields, setDateTime: dateTime); return DateModifier._private(DateEditAction.setCustom, fields: fields, setDateTime: dateTime);
} }
factory DateModifier.copyField(Set<MetadataField> fields, DateFieldSource copyFieldSource) { factory DateModifier.copyField(DateFieldSource copyFieldSource) {
return DateModifier._private(DateEditAction.copyField, fields, copyFieldSource: copyFieldSource); return DateModifier._private(DateEditAction.copyField, copyFieldSource: copyFieldSource);
} }
factory DateModifier.extractFromTitle(Set<MetadataField> fields) { factory DateModifier.extractFromTitle() {
return DateModifier._private(DateEditAction.extractFromTitle, fields); return const DateModifier._private(DateEditAction.extractFromTitle);
} }
factory DateModifier.shift(Set<MetadataField> fields, int shiftMinutes) { factory DateModifier.shift(Set<MetadataField> fields, int shiftMinutes) {
return DateModifier._private(DateEditAction.shift, fields, shiftMinutes: shiftMinutes); return DateModifier._private(DateEditAction.shift, fields: fields, shiftMinutes: shiftMinutes);
} }
factory DateModifier.remove(Set<MetadataField> fields) { factory DateModifier.remove(Set<MetadataField> fields) {
return DateModifier._private(DateEditAction.remove, fields); return DateModifier._private(DateEditAction.remove, fields: fields);
} }
} }

View file

@ -3,6 +3,7 @@ import 'package:aves/model/metadata/fields.dart';
enum DateEditAction { enum DateEditAction {
setCustom, setCustom,
copyField, copyField,
copyItem,
extractFromTitle, extractFromTitle,
shift, shift,
remove, remove,

View file

@ -427,7 +427,8 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
final todoItems = await _getEditableTargetItems(context, canEdit: (entry) => entry.canEditDate); final todoItems = await _getEditableTargetItems(context, canEdit: (entry) => entry.canEditDate);
if (todoItems == null || todoItems.isEmpty) return; if (todoItems == null || todoItems.isEmpty) return;
final modifier = await selectDateModifier(context, todoItems); final collection = context.read<CollectionLens>();
final modifier = await selectDateModifier(context, todoItems, collection);
if (modifier == null) return; if (modifier == null) return;
await _edit(context, todoItems, (entry) => entry.editDate(modifier)); await _edit(context, todoItems, (entry) => entry.editDate(modifier));

View file

@ -14,13 +14,14 @@ import 'package:flutter/material.dart';
import 'package:latlong2/latlong.dart'; import 'package:latlong2/latlong.dart';
mixin EntryEditorMixin { mixin EntryEditorMixin {
Future<DateModifier?> selectDateModifier(BuildContext context, Set<AvesEntry> entries) async { Future<DateModifier?> selectDateModifier(BuildContext context, Set<AvesEntry> entries, CollectionLens? collection) async {
if (entries.isEmpty) return null; if (entries.isEmpty) return null;
final modifier = await showDialog<DateModifier>( final modifier = await showDialog<DateModifier>(
context: context, context: context,
builder: (context) => EditEntryDateDialog( builder: (context) => EditEntryDateDialog(
entry: entries.first, entry: entries.first,
collection: collection,
), ),
); );
return modifier; return modifier;

View file

@ -56,7 +56,7 @@ class GridItemSelectionOverlay<T> extends StatelessWidget {
return child; return child;
}, },
) )
: const SizedBox.shrink(); : const SizedBox();
return AnimatedSwitcher( return AnimatedSwitcher(
duration: duration, duration: duration,
child: child, child: child,

View file

@ -2,10 +2,9 @@ import 'package:aves/model/covers.dart';
import 'package:aves/model/entry.dart'; import 'package:aves/model/entry.dart';
import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/fx/borders.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
import 'package:aves/widgets/common/thumbnail/image.dart';
import 'package:aves/widgets/dialogs/item_pick_dialog.dart'; import 'package:aves/widgets/dialogs/item_pick_dialog.dart';
import 'package:aves/widgets/dialogs/item_picker.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -66,7 +65,11 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
Container( Container(
alignment: Alignment.center, alignment: Alignment.center,
padding: const EdgeInsets.only(top: 16), padding: const EdgeInsets.only(top: 16),
child: _buildCover(_coverEntry!, extent), child: ItemPicker(
extent: extent,
entry: _coverEntry!,
onTap: _pickEntry,
),
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 24), padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 24),
@ -103,29 +106,6 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
); );
} }
Widget _buildCover(AvesEntry entry, double extent) {
return GestureDetector(
onTap: _pickEntry,
child: Container(
decoration: BoxDecoration(
border: AvesBorder.border(context),
borderRadius: const BorderRadius.all(Radius.circular(32)),
),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(32)),
child: SizedBox(
width: extent,
height: extent,
child: ThumbnailImage(
entry: entry,
extent: extent,
),
),
),
),
);
}
Future<void> _pickEntry() async { Future<void> _pickEntry() async {
final _collection = widget.collection; final _collection = widget.collection;
if (_collection == null) return; if (_collection == null) return;

View file

@ -2,6 +2,7 @@ import 'package:aves/model/entry.dart';
import 'package:aves/model/metadata/date_modifier.dart'; import 'package:aves/model/metadata/date_modifier.dart';
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums.dart';
import 'package:aves/model/metadata/fields.dart'; import 'package:aves/model/metadata/fields.dart';
import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/theme/durations.dart'; import 'package:aves/theme/durations.dart';
import 'package:aves/theme/format.dart'; import 'package:aves/theme/format.dart';
import 'package:aves/theme/icons.dart'; import 'package:aves/theme/icons.dart';
@ -10,15 +11,19 @@ import 'package:aves/widgets/common/basic/wheel.dart';
import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
import 'package:aves/widgets/dialogs/aves_dialog.dart'; import 'package:aves/widgets/dialogs/aves_dialog.dart';
import 'package:aves/widgets/dialogs/item_pick_dialog.dart';
import 'package:aves/widgets/dialogs/item_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class EditEntryDateDialog extends StatefulWidget { class EditEntryDateDialog extends StatefulWidget {
final AvesEntry entry; final AvesEntry entry;
final CollectionLens? collection;
const EditEntryDateDialog({ const EditEntryDateDialog({
Key? key, Key? key,
required this.entry, required this.entry,
this.collection,
}) : super(key: key); }) : super(key: key);
@override @override
@ -28,16 +33,20 @@ class EditEntryDateDialog extends StatefulWidget {
class _EditEntryDateDialogState extends State<EditEntryDateDialog> { class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
DateEditAction _action = DateEditAction.setCustom; DateEditAction _action = DateEditAction.setCustom;
DateFieldSource _copyFieldSource = DateFieldSource.fileModifiedDate; DateFieldSource _copyFieldSource = DateFieldSource.fileModifiedDate;
late AvesEntry _copyItemSource;
late DateTime _setDateTime; late DateTime _setDateTime;
late ValueNotifier<int> _shiftHour, _shiftMinute; late ValueNotifier<int> _shiftHour, _shiftMinute;
late ValueNotifier<String> _shiftSign; late ValueNotifier<String> _shiftSign;
bool _showOptions = false; bool _showOptions = false;
final Set<MetadataField> _fields = {...DateModifier.writableDateFields}; final Set<MetadataField> _fields = {...DateModifier.writableDateFields};
DateTime get copyItemDate => _copyItemSource.bestDate ?? DateTime.now();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initSet(); _initSet();
_initCopyItem();
_initShift(60); _initShift(60);
} }
@ -45,6 +54,10 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
_setDateTime = widget.entry.bestDate ?? DateTime.now(); _setDateTime = widget.entry.bestDate ?? DateTime.now();
} }
void _initCopyItem() {
_copyItemSource = widget.entry;
}
void _initShift(int initialMinutes) { void _initShift(int initialMinutes) {
final abs = initialMinutes.abs(); final abs = initialMinutes.abs();
_shiftHour = ValueNotifier(abs ~/ 60); _shiftHour = ValueNotifier(abs ~/ 60);
@ -91,6 +104,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
children: [ children: [
if (_action == DateEditAction.setCustom) _buildSetCustomContent(context), if (_action == DateEditAction.setCustom) _buildSetCustomContent(context),
if (_action == DateEditAction.copyField) _buildCopyFieldContent(context), if (_action == DateEditAction.copyField) _buildCopyFieldContent(context),
if (_action == DateEditAction.copyItem) _buildCopyItemContent(context),
if (_action == DateEditAction.shift) _buildShiftContent(context), if (_action == DateEditAction.shift) _buildShiftContent(context),
(_action == DateEditAction.shift || _action == DateEditAction.remove) ? _buildDestinationFields(context) : const SizedBox(height: 8), (_action == DateEditAction.shift || _action == DateEditAction.remove) ? _buildDestinationFields(context) : const SizedBox(height: 8),
], ],
@ -170,6 +184,27 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
); );
} }
Widget _buildCopyItemContent(BuildContext context) {
final l10n = context.l10n;
final locale = l10n.localeName;
final use24hour = context.select<MediaQueryData, bool>((v) => v.alwaysUse24HourFormat);
return Padding(
padding: const EdgeInsetsDirectional.only(start: 16, end: 8),
child: Row(
children: [
Expanded(child: Text(formatDateTime(copyItemDate, locale, use24hour))),
const SizedBox(width: 8),
ItemPicker(
extent: 48,
entry: _copyItemSource,
onTap: _pickCopyItemSource,
),
],
),
);
}
Widget _buildShiftContent(BuildContext context) { Widget _buildShiftContent(BuildContext context) {
const textStyle = TextStyle(fontSize: 34); const textStyle = TextStyle(fontSize: 34);
return Center( return Center(
@ -268,6 +303,8 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
return l10n.editEntryDateDialogSetCustom; return l10n.editEntryDateDialogSetCustom;
case DateEditAction.copyField: case DateEditAction.copyField:
return l10n.editEntryDateDialogCopyField; return l10n.editEntryDateDialogCopyField;
case DateEditAction.copyItem:
return l10n.editEntryDateDialogCopyItem;
case DateEditAction.extractFromTitle: case DateEditAction.extractFromTitle:
return l10n.editEntryDateDialogExtractFromTitle; return l10n.editEntryDateDialogExtractFromTitle;
case DateEditAction.shift: case DateEditAction.shift:
@ -335,6 +372,27 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
)); ));
} }
Future<void> _pickCopyItemSource() async {
final _collection = widget.collection;
if (_collection == null) return;
final entry = await Navigator.push(
context,
MaterialPageRoute(
settings: const RouteSettings(name: ItemPickDialog.routeName),
builder: (context) => ItemPickDialog(
collection: CollectionLens(
source: _collection.source,
),
),
fullscreenDialog: true,
),
);
if (entry != null) {
setState(() => _copyItemSource = entry);
}
}
DateModifier _getModifier() { DateModifier _getModifier() {
// fields to modify are only set for the `shift` and `remove` actions, // fields to modify are only set for the `shift` and `remove` actions,
// as the effective fields for the other actions will depend on // as the effective fields for the other actions will depend on
@ -343,9 +401,11 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
case DateEditAction.setCustom: case DateEditAction.setCustom:
return DateModifier.setCustom(const {}, _setDateTime); return DateModifier.setCustom(const {}, _setDateTime);
case DateEditAction.copyField: case DateEditAction.copyField:
return DateModifier.copyField(const {}, _copyFieldSource); return DateModifier.copyField(_copyFieldSource);
case DateEditAction.copyItem:
return DateModifier.setCustom(const {}, copyItemDate);
case DateEditAction.extractFromTitle: case DateEditAction.extractFromTitle:
return DateModifier.extractFromTitle(const {}); return DateModifier.extractFromTitle();
case DateEditAction.shift: case DateEditAction.shift:
final shiftTotalMinutes = (_shiftHour.value * 60 + _shiftMinute.value) * (_shiftSign.value == '+' ? 1 : -1); final shiftTotalMinutes = (_shiftHour.value * 60 + _shiftMinute.value) * (_shiftSign.value == '+' ? 1 : -1);
return DateModifier.shift(_fields, shiftTotalMinutes); return DateModifier.shift(_fields, shiftTotalMinutes);

View file

@ -2,11 +2,11 @@ import 'package:aves/model/entry.dart';
import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/model/source/collection_source.dart'; import 'package:aves/model/source/collection_source.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
import 'package:aves/widgets/dialogs/aves_dialog.dart'; import 'package:aves/widgets/dialogs/aves_dialog.dart';
import 'package:aves/widgets/dialogs/item_pick_dialog.dart'; import 'package:aves/widgets/dialogs/item_pick_dialog.dart';
import 'package:aves/widgets/dialogs/item_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@ -72,11 +72,12 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
children: [ children: [
title, title,
const Spacer(), const Spacer(),
IconButton( if (_customEntry != null)
icon: const Icon(AIcons.setCover), ItemPicker(
onPressed: _isCustom ? _pickEntry : null, extent: 46,
tooltip: context.l10n.changeTooltip, entry: _customEntry!,
), onTap: _pickEntry,
),
], ],
) )
: title, : title,

View file

@ -0,0 +1,72 @@
import 'dart:math';
import 'package:aves/model/entry.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/fx/borders.dart';
import 'package:aves/widgets/common/thumbnail/image.dart';
import 'package:flutter/material.dart';
class ItemPicker extends StatelessWidget {
final double extent;
final AvesEntry entry;
final GestureTapCallback? onTap;
const ItemPicker({
Key? key,
required this.extent,
required this.entry,
this.onTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final imageBorderRadius = BorderRadius.all(Radius.circular(extent * .25));
final actionBoxDimension = min(40.0, extent * .4);
final actionBoxBorderRadius = BorderRadiusDirectional.only(topStart: Radius.circular(actionBoxDimension * .6));
return Tooltip(
message: context.l10n.changeTooltip,
child: GestureDetector(
onTap: onTap,
child: Container(
decoration: BoxDecoration(
border: AvesBorder.border(context),
borderRadius: imageBorderRadius,
),
child: ClipRRect(
borderRadius: imageBorderRadius,
child: SizedBox(
width: extent,
height: extent,
child: Stack(
children: [
ThumbnailImage(
entry: entry,
extent: extent,
),
PositionedDirectional(
end: -1,
bottom: -1,
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).brightness == Brightness.dark ? const Color(0xAA000000) : const Color(0xCCFFFFFF),
border: AvesBorder.border(context),
borderRadius: actionBoxBorderRadius,
),
width: actionBoxDimension,
height: actionBoxDimension,
child: Icon(
AIcons.edit,
size: actionBoxDimension * .6,
),
),
),
],
),
),
),
),
),
);
}
}

View file

@ -97,7 +97,7 @@ class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin, EntryEdi
} }
Future<void> _editDate(BuildContext context) async { Future<void> _editDate(BuildContext context) async {
final modifier = await selectDateModifier(context, {entry}); final modifier = await selectDateModifier(context, {entry}, collection);
if (modifier == null) return; if (modifier == null) return;
await edit(context, () => entry.editDate(modifier)); await edit(context, () => entry.editDate(modifier));

View file

@ -3,6 +3,7 @@
"themeBrightnessLight", "themeBrightnessLight",
"themeBrightnessDark", "themeBrightnessDark",
"themeBrightnessBlack", "themeBrightnessBlack",
"editEntryDateDialogCopyItem",
"settingsSectionDisplay", "settingsSectionDisplay",
"settingsThemeBrightness", "settingsThemeBrightness",
"settingsThemeColorful" "settingsThemeColorful"
@ -12,6 +13,7 @@
"themeBrightnessLight", "themeBrightnessLight",
"themeBrightnessDark", "themeBrightnessDark",
"themeBrightnessBlack", "themeBrightnessBlack",
"editEntryDateDialogCopyItem",
"settingsSectionDisplay", "settingsSectionDisplay",
"settingsThemeBrightness", "settingsThemeBrightness",
"settingsThemeColorful" "settingsThemeColorful"
@ -21,6 +23,7 @@
"themeBrightnessLight", "themeBrightnessLight",
"themeBrightnessDark", "themeBrightnessDark",
"themeBrightnessBlack", "themeBrightnessBlack",
"editEntryDateDialogCopyItem",
"settingsSectionDisplay", "settingsSectionDisplay",
"settingsThemeBrightness", "settingsThemeBrightness",
"settingsThemeColorful" "settingsThemeColorful"
@ -36,6 +39,7 @@
"themeBrightnessLight", "themeBrightnessLight",
"themeBrightnessDark", "themeBrightnessDark",
"themeBrightnessBlack", "themeBrightnessBlack",
"editEntryDateDialogCopyItem",
"settingsViewerShowOverlayThumbnails", "settingsViewerShowOverlayThumbnails",
"settingsVideoControlsTile", "settingsVideoControlsTile",
"settingsVideoControlsTitle", "settingsVideoControlsTitle",
@ -52,6 +56,7 @@
"themeBrightnessLight", "themeBrightnessLight",
"themeBrightnessDark", "themeBrightnessDark",
"themeBrightnessBlack", "themeBrightnessBlack",
"editEntryDateDialogCopyItem",
"settingsSectionDisplay", "settingsSectionDisplay",
"settingsThemeBrightness", "settingsThemeBrightness",
"settingsThemeColorful" "settingsThemeColorful"
@ -61,6 +66,7 @@
"themeBrightnessLight", "themeBrightnessLight",
"themeBrightnessDark", "themeBrightnessDark",
"themeBrightnessBlack", "themeBrightnessBlack",
"editEntryDateDialogCopyItem",
"settingsSectionDisplay", "settingsSectionDisplay",
"settingsThemeBrightness", "settingsThemeBrightness",
"settingsThemeColorful" "settingsThemeColorful"
@ -70,6 +76,7 @@
"themeBrightnessLight", "themeBrightnessLight",
"themeBrightnessDark", "themeBrightnessDark",
"themeBrightnessBlack", "themeBrightnessBlack",
"editEntryDateDialogCopyItem",
"settingsSectionDisplay", "settingsSectionDisplay",
"settingsThemeBrightness", "settingsThemeBrightness",
"settingsThemeColorful" "settingsThemeColorful"
@ -79,6 +86,7 @@
"themeBrightnessLight", "themeBrightnessLight",
"themeBrightnessDark", "themeBrightnessDark",
"themeBrightnessBlack", "themeBrightnessBlack",
"editEntryDateDialogCopyItem",
"settingsSectionDisplay", "settingsSectionDisplay",
"settingsThemeBrightness", "settingsThemeBrightness",
"settingsThemeColorful" "settingsThemeColorful"