adding packages

This commit is contained in:
2026-01-15 14:38:46 -08:00
parent ef86e3ab6a
commit 6869cf47e5
5253 changed files with 726695 additions and 34 deletions
@@ -0,0 +1,77 @@
import 'setting_impl.dart';
class BoolSettingTemplate implements SettingsImpl {
bool defaultValue;
String name;
bool isPrivate;
bool addStream = true;
bool addValueNotifier = true;
@override
String preInit() {
return '${name}Notify($defaultValue);';
}
@override
String postInit() {
return '${name}Notify($name);';
}
@override
String dispose() {
final sb = StringBuffer();
if (addStream) {
sb.writeln(' _${name}Controller.close();');
}
return sb.toString();
}
@override
String toString() {
final sb = StringBuffer();
if (addStream) {
sb.writeln(
'final _${name}Controller = StreamController<bool>.broadcast();');
sb.writeln(
'Stream<bool> get ${name}Stream => _${name}Controller.stream;');
}
if (addValueNotifier) {
sb.writeln('final _${name}Notifier = ValueNotifier<bool>($defaultValue);');
sb.writeln('ValueListenable<bool> get ${name}Notifier => _${name}Notifier;');
}
sb.writeln("""
@override
bool get $name {
return prefs?.getBool('$name') ?? $defaultValue;
}
@override
set $name(bool value) {
${name}Async(value);
}
Future<bool> ${name}Async(bool value) async {
final success = await prefs.setBool('$name', value);
if (success) {
${name}Notify(value);
}
return success;
}
""");
sb.writeln('void ${name}Notify(bool value) {');
if (addStream) {
sb.writeln(' _${name}Controller.add(value);');
}
if (addValueNotifier) {
sb.writeln('_${name}Notifier.value = value;');
}
sb.writeln('_controller.add(this);');
sb.writeln('}');
return sb.toString();
}
}
@@ -0,0 +1,25 @@
import 'package:settings_gen/src/template/util.dart';
class CommaList<T> {
CommaList(this.templates) : assert(templates != null);
final List<T> templates;
@override
String toString() =>
templates.map((t) => t.toString()).where((s) => s.isNotEmpty).join(', ');
}
class SurroundedCommaList<T> {
SurroundedCommaList(this.prefix, this.suffix, this.templates)
: assert(prefix != null),
assert(suffix != null),
assert(templates != null);
final String prefix;
final String suffix;
final List<T> templates;
@override
String toString() => surroundNonEmpty(prefix, suffix, CommaList(templates));
}
@@ -0,0 +1,78 @@
import 'setting_impl.dart';
class DoubleSettingTemplate implements SettingsImpl {
double defaultValue;
String name;
bool isPrivate;
bool addStream = true;
bool addValueNotifier = true;
@override
String preInit() {
return '${name}Notify($defaultValue);';
}
@override
String postInit() {
return '${name}Notify($name);';
}
@override
String dispose() {
final sb = StringBuffer();
if (addStream) {
sb.writeln(' _${name}Controller.close();');
}
return sb.toString();
}
@override
String toString() {
final sb = StringBuffer();
if (addStream) {
sb.writeln(
'final _${name}Controller = StreamController<double>.broadcast();');
sb.writeln(
'Stream<double> get ${name}Stream => _${name}Controller.stream;');
}
if (addValueNotifier) {
sb.writeln('final _${name}Notifier = ValueNotifier<double>($defaultValue);');
sb.writeln(
'ValueListenable<double> get ${name}Notifier => _${name}Notifier;');
}
sb.writeln("""
@override
double get $name {
return prefs?.getDouble('$name') ?? $defaultValue;
}
@override
set $name(double value) {
${name}Async(value);
}
Future<bool> ${name}Async(double value) async {
final success = await prefs.setDouble('$name', value);
if (success) {
${name}Notify(value);
}
return success;
}
""");
sb.writeln('void ${name}Notify(double value) {');
if (addStream) {
sb.writeln(' _${name}Controller.add(value);');
}
if (addValueNotifier) {
sb.writeln('_${name}Notifier.value = value;');
}
sb.writeln('_controller.add(this);');
sb.writeln('}');
return sb.toString();
}
}
@@ -0,0 +1,76 @@
import 'setting_impl.dart';
class IntSettingTemplate implements SettingsImpl {
int defaultValue;
String name;
bool isPrivate;
bool addStream = true;
bool addValueNotifier = true;
@override
String preInit() {
return '${name}Notify($defaultValue);';
}
@override
String postInit() {
return '${name}Notify($name);';
}
@override
String dispose() {
final sb = StringBuffer();
if (addStream) {
sb.writeln(' _${name}Controller.close();');
}
return sb.toString();
}
@override
String toString() {
final sb = StringBuffer();
if (addStream) {
sb.writeln(
'final _${name}Controller = StreamController<int>.broadcast();');
sb.writeln('Stream<int> get ${name}Stream => _${name}Controller.stream;');
}
if (addValueNotifier) {
sb.writeln('final _${name}Notifier = ValueNotifier<int>($defaultValue);');
sb.writeln('ValueListenable<int> get ${name}Notifier => _${name}Notifier;');
}
sb.writeln("""
@override
int get $name {
return prefs?.getInt('$name') ?? $defaultValue;
}
@override
set $name(int value) {
${name}Async(value);
}
Future<bool> ${name}Async(int value) async {
final success = await prefs.setInt('$name', value);
if (success) {
${name}Notify(value);
}
return success;
}
""");
sb.writeln('void ${name}Notify(int value) {');
if (addStream) {
sb.writeln(' _${name}Controller.add(value);');
}
if (addValueNotifier) {
sb.writeln('_${name}Notifier.value = value;');
}
sb.writeln('_controller.add(this);');
sb.writeln('}');
return sb.toString();
}
}
@@ -0,0 +1,34 @@
class ParamTemplate {
String name;
String type;
String defaultValue;
bool hasRequiredAnnotation = false;
String get asArgument => name;
NamedArgTemplate get asNamedArgument => NamedArgTemplate()..name = name;
String get metadata => hasRequiredAnnotation ? '@required ' : '';
@override
String toString() => defaultValue == null
? '$metadata$type $name'
: '$type $name = $defaultValue';
}
class TypeParamTemplate {
String name;
String bound;
String get asArgument => name;
@override
String toString() => bound == null ? name : '$name extends $bound';
}
class NamedArgTemplate {
String name;
@override
String toString() => '$name: $name';
}
@@ -0,0 +1,12 @@
class Rows<T> {
final List<T> _templates = [];
void add(T template) => _templates.add(template);
bool get isEmpty => _templates.isEmpty;
List get templates => _templates;
@override
String toString() =>
_templates.map((t) => t.toString()).where((s) => s.isNotEmpty).join('\n');
}
@@ -0,0 +1,5 @@
abstract class SettingsImpl {
String preInit();
String postInit();
String dispose();
}
@@ -0,0 +1,140 @@
import 'bool_setting.dart';
import 'comma_list.dart';
import 'double_setting.dart';
import 'int_setting.dart';
import 'params.dart';
import 'rows.dart';
import 'setting_impl.dart';
import 'string_list_setting.dart';
import 'string_setting.dart';
class MixinStoreTemplate extends StoreTemplate {
String get typeName => '_\$$publicTypeName';
@override
String toString() => '''
mixin $typeName$typeParams on $parentTypeName$typeArgs, SettingsStore {
$storeBody
}''';
}
abstract class StoreTemplate {
final SurroundedCommaList<TypeParamTemplate> typeParams =
SurroundedCommaList('<', '>', []);
final SurroundedCommaList<String> typeArgs =
SurroundedCommaList('<', '>', []);
String publicTypeName;
String parentTypeName;
final Rows<BoolSettingTemplate> boolSettings = Rows();
final Rows<StringSettingTemplate> stringSettings = Rows();
final Rows<IntSettingTemplate> intSettings = Rows();
final Rows<DoubleSettingTemplate> doubleSettings = Rows();
final Rows<StringListSettingTemplate> stringListSettings = Rows();
final List<String> toStringList = [];
bool generateToString = false;
String _actionControllerName;
String get actionControllerName =>
_actionControllerName ??= '_\$${parentTypeName}ActionController';
String get storeBody {
var toStringMethod = '';
final sb = StringBuffer();
sb.writeln('SharedPreferences prefs;');
sb.writeln(
'final _controller = StreamController<$publicTypeName>.broadcast();');
sb.writeln('Stream<$publicTypeName> get stream => _controller.stream;');
sb.writeln();
List<SettingsImpl> _settingsImpl = [];
_settingsImpl.addAll(
boolSettings.templates.whereType<SettingsImpl>().map((t) => t).toList(),
);
_settingsImpl.addAll(
stringSettings.templates.whereType<SettingsImpl>().map((t) => t).toList(),
);
_settingsImpl.addAll(
intSettings.templates.whereType<SettingsImpl>().map((t) => t).toList(),
);
_settingsImpl.addAll(
doubleSettings.templates.whereType<SettingsImpl>().map((t) => t).toList(),
);
_settingsImpl.addAll(
stringListSettings.templates
.whereType<SettingsImpl>()
.map((t) => t)
.toList(),
);
sb.writeln(' Future<bool> init() async {');
for (final setting in _settingsImpl) {
sb.writeln(setting.preInit());
}
sb.writeln(' prefs = await SharedPreferences.getInstance();');
for (final setting in _settingsImpl) {
sb.writeln(setting.postInit());
}
sb.writeln(' return prefs != null;');
sb.writeln(' }');
sb.writeln();
sb.writeln('$boolSettings');
sb.writeln();
sb.writeln('$stringSettings');
sb.writeln();
sb.writeln('$intSettings');
sb.writeln();
sb.writeln('$doubleSettings');
sb.writeln();
sb.writeln('$stringListSettings');
sb.writeln();
sb.writeln(' void dispose() {');
for (final setting in _settingsImpl) {
sb.writeln(setting.dispose());
}
sb.writeln('_controller.close();');
sb.writeln(' }');
sb.writeln();
final baseBody = sb.toString();
if (generateToString) {
final publicBoolSettings = boolSettings.templates
..removeWhere((element) => element.isPrivate);
final publicStringSettings = stringSettings.templates
..removeWhere((element) => element.isPrivate);
final publicIntSettings = intSettings.templates
..removeWhere((element) => element.isPrivate);
final publicDoubleSettings = doubleSettings.templates
..removeWhere((element) => element.isPrivate);
final publicStringListSettings = doubleSettings.templates
..removeWhere((element) => element.isPrivate);
toStringList
..addAll(publicBoolSettings.map(
(current) => '${current.name}: \${${current.name}.toString()}'))
..addAll(publicStringSettings.map(
(current) => '${current.name}: \${${current.name}.toString()}'))
..addAll(publicIntSettings.map(
(current) => '${current.name}: \${${current.name}.toString()}'))
..addAll(publicDoubleSettings.map(
(current) => '${current.name}: \${${current.name}.toString()}'))
..addAll(publicStringListSettings.map(
(current) => '${current.name}: \${${current.name}.toString()}'));
toStringMethod = '''
@override
String toString() {
final string = \'${toStringList.join(',')}\';
return '{\$string}';
}
''';
}
return baseBody + toStringMethod;
}
@override
String toString();
}
@@ -0,0 +1,15 @@
const _analyzerIgnores =
'// ignore_for_file: non_constant_identifier_names, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic';
class StoreFileTemplate {
Iterable<String> storeSources;
@override
String toString() => storeSources.isEmpty
? ''
: '''
$_analyzerIgnores
${storeSources.join('\n\n')}
''';
}
@@ -0,0 +1,77 @@
import 'setting_impl.dart';
class StringListSettingTemplate implements SettingsImpl {
List<String> defaultValue;
String name;
bool isPrivate;
bool addStream = true;
bool addValueNotifier = true;
@override
String preInit() {
return "${name}Notify($defaultValue);";
}
@override
String postInit() {
return '${name}Notify($name);';
}
@override
String dispose() {
final sb = StringBuffer();
if (addStream) {
sb.writeln(' _${name}Controller.close();');
}
return sb.toString();
}
@override
String toString() {
final sb = StringBuffer();
if (addStream) {
sb.writeln(
'final _${name}Controller = StreamController<List<String>>.broadcast();');
sb.writeln(
'Stream<List<String>> get ${name}Stream => _${name}Controller.stream;');
}
if (addValueNotifier) {
sb.writeln('final _${name}Notifier = ValueNotifier<List<String>>($defaultValue);');
sb.writeln('ValueListenable<List<String>> get ${name}Notifier => _${name}Notifier;');
}
sb.writeln("""
@override
List<String> get $name {
return prefs?.getStringList('$name') ?? $defaultValue;
}
@override
set $name(List<String> value) {
${name}Async(value);
}
Future<bool> ${name}Async(List<String> value) async {
final success = await prefs.setStringList('$name', value);
if (success) {
${name}Notify(value);
}
return success;
}
""");
sb.writeln('void ${name}Notify(List<String> value) {');
if (addStream) {
sb.writeln(' _${name}Controller.add(value);');
}
if (addValueNotifier) {
sb.writeln('_${name}Notifier.value = value;');
}
sb.writeln('_controller.add(this);');
sb.writeln('}');
return sb.toString();
}
}
@@ -0,0 +1,77 @@
import 'setting_impl.dart';
class StringSettingTemplate implements SettingsImpl {
String defaultValue;
String name;
bool isPrivate;
bool addStream = true;
bool addValueNotifier = true;
@override
String preInit() {
return "${name}Notify('$defaultValue');";
}
@override
String postInit() {
return '${name}Notify($name);';
}
@override
String dispose() {
final sb = StringBuffer();
if (addStream) {
sb.writeln(' _${name}Controller.close();');
}
return sb.toString();
}
@override
String toString() {
final sb = StringBuffer();
if (addStream) {
sb.writeln(
'final _${name}Controller = StreamController<String>.broadcast();');
sb.writeln(
'Stream<String> get ${name}Stream => _${name}Controller.stream;');
}
if (addValueNotifier) {
sb.writeln("final _${name}Notifier = ValueNotifier<String>('$defaultValue');");
sb.writeln('ValueListenable<String> get ${name}Notifier => _${name}Notifier;');
}
sb.writeln("""
@override
String get $name {
return prefs?.getString('$name') ?? '$defaultValue';
}
@override
set $name(String value) {
${name}Async(value);
}
Future<bool> ${name}Async(String value) async {
final success = await prefs.setString('$name', value);
if (success) {
${name}Notify(value);
}
return success;
}
""");
sb.writeln('void ${name}Notify(String value) {');
if (addStream) {
sb.writeln(' _${name}Controller.add(value);');
}
if (addValueNotifier) {
sb.writeln('_${name}Notifier.value = value;');
}
sb.writeln('_controller.add(this);');
sb.writeln('}');
return sb.toString();
}
}
@@ -0,0 +1,42 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:settings_gen/src/template/params.dart';
import 'package:settings_gen/src/type_names.dart';
import 'package:source_gen/source_gen.dart';
// ignore: avoid_annotating_with_dynamic
String surroundNonEmpty(String prefix, String suffix, dynamic content) {
final contentStr = content.toString();
return contentStr.isEmpty ? '' : '$prefix$contentStr$suffix';
}
const _streamChecker = TypeChecker.fromRuntime(Stream);
class AsyncMethodChecker {
AsyncMethodChecker([TypeChecker checkStream]) {
_checkStream = checkStream ?? _streamChecker;
}
TypeChecker _checkStream;
bool returnsFuture(MethodElement method) =>
method.returnType.isDartAsyncFuture ||
(method.isAsynchronous &&
!method.isGenerator &&
method.returnType.isDynamic);
bool returnsStream(MethodElement method) =>
_checkStream.isAssignableFromType(method.returnType) ||
(method.isAsynchronous &&
method.isGenerator &&
method.returnType.isDynamic);
}
TypeParamTemplate typeParamTemplate(
TypeParameterElement param,
LibraryScopedNameFinder typeNameFinder,
) =>
TypeParamTemplate()
..name = param.name
..bound = param.bound != null
? typeNameFinder.findTypeParameterBoundsTypeName(param)
: null;