Optimize pref streams where the first value should be ignored

This commit is contained in:
Ming Ming 2024-02-25 12:09:57 +08:00
parent c588ab9c6d
commit def24946e2
36 changed files with 550 additions and 152 deletions

View file

@ -219,7 +219,7 @@ class HomeSearchSuggestionBloc
}
try {
final persons = await ListPerson(_c)(
account, accountPrefController.personProvider.value)
account, accountPrefController.personProviderValue)
.last;
product.addAll(persons.map((t) => _PersonSearcheable(t)));
_log.info("[_onEventPreloadData] Loaded ${persons.length} people");

View file

@ -8,6 +8,7 @@ import 'package:rxdart/rxdart.dart';
part 'account_pref_controller.g.dart';
@npLog
@npSubjectAccessor
class AccountPrefController {
AccountPrefController({
required this.account,
@ -20,34 +21,24 @@ class AccountPrefController {
_isEnableMemoryAlbumController.close();
}
ValueStream<String> get shareFolder => _shareFolderController.stream;
Future<void> setShareFolder(String value) => _set<String>(
controller: _shareFolderController,
setter: (pref, value) => pref.setShareFolder(value),
value: value,
);
ValueStream<String?> get accountLabel => _accountLabelController.stream;
Future<void> setAccountLabel(String? value) => _set<String?>(
controller: _accountLabelController,
setter: (pref, value) => pref.setAccountLabel(value),
value: value,
);
ValueStream<PersonProvider> get personProvider =>
_personProviderController.stream;
Future<void> setPersonProvider(PersonProvider value) => _set<PersonProvider>(
controller: _personProviderController,
setter: (pref, value) => pref.setPersonProvider(value.index),
value: value,
);
ValueStream<bool> get isEnableMemoryAlbum =>
_isEnableMemoryAlbumController.stream;
Future<void> setEnableMemoryAlbum(bool value) => _set<bool>(
controller: _isEnableMemoryAlbumController,
setter: (pref, value) => pref.setEnableMemoryAlbum(value),
@ -76,12 +67,16 @@ class AccountPrefController {
final Account account;
final AccountPref _accountPref;
@npSubjectAccessor
late final _shareFolderController =
BehaviorSubject.seeded(_accountPref.getShareFolderOr(""));
@npSubjectAccessor
late final _accountLabelController =
BehaviorSubject.seeded(_accountPref.getAccountLabel());
@npSubjectAccessor
late final _personProviderController = BehaviorSubject.seeded(
PersonProvider.fromValue(_accountPref.getPersonProviderOr()));
@npSubjectAccessor
late final _isEnableMemoryAlbumController =
BehaviorSubject.seeded(_accountPref.isEnableMemoryAlbumOr(true));
}

View file

@ -13,3 +13,34 @@ extension _$AccountPrefControllerNpLog on AccountPrefController {
static final log =
Logger("controller.account_pref_controller.AccountPrefController");
}
// **************************************************************************
// NpSubjectAccessorGenerator
// **************************************************************************
extension $AccountPrefControllerNpSubjectAccessor on AccountPrefController {
// _shareFolderController
ValueStream<String> get shareFolder => _shareFolderController.stream;
Stream<String> get shareFolderNew => shareFolder.skip(1);
Stream<String> get shareFolderChange => shareFolder.distinct().skip(1);
String get shareFolderValue => _shareFolderController.value;
// _accountLabelController
ValueStream<String?> get accountLabel => _accountLabelController.stream;
Stream<String?> get accountLabelNew => accountLabel.skip(1);
Stream<String?> get accountLabelChange => accountLabel.distinct().skip(1);
String? get accountLabelValue => _accountLabelController.value;
// _personProviderController
ValueStream<PersonProvider> get personProvider =>
_personProviderController.stream;
Stream<PersonProvider> get personProviderNew => personProvider.skip(1);
Stream<PersonProvider> get personProviderChange =>
personProvider.distinct().skip(1);
PersonProvider get personProviderValue => _personProviderController.value;
// _isEnableMemoryAlbumController
ValueStream<bool> get isEnableMemoryAlbum =>
_isEnableMemoryAlbumController.stream;
Stream<bool> get isEnableMemoryAlbumNew => isEnableMemoryAlbum.skip(1);
Stream<bool> get isEnableMemoryAlbumChange =>
isEnableMemoryAlbum.distinct().skip(1);
bool get isEnableMemoryAlbumValue => _isEnableMemoryAlbumController.value;
}

View file

@ -43,7 +43,7 @@ class FilesController {
required this.account,
required this.accountPrefController,
}) {
_subscriptions.add(accountPrefController.shareFolder.listen((event) {
_subscriptions.add(accountPrefController.shareFolderChange.listen((event) {
// sync remote if share folder is modified
if (_isDataStreamInited) {
syncRemote();
@ -84,7 +84,7 @@ class FilesController {
try {
final shareDir = File(
path: file_util.unstripPath(
account, accountPrefController.shareFolder.value),
account, accountPrefController.shareFolderValue),
);
var isShareDirIncluded = false;
@ -320,7 +320,7 @@ class FilesController {
final completer = Completer();
ListFile(_c)(
account,
file_util.unstripPath(account, accountPrefController.shareFolder.value),
file_util.unstripPath(account, accountPrefController.shareFolderValue),
).listen(
(ev) {
lastData = _convertListResultsToEvent(ev, hasNext: true);
@ -338,7 +338,7 @@ class FilesController {
final completer = Completer();
ListFile(_c)(
account,
file_util.unstripPath(account, accountPrefController.shareFolder.value),
file_util.unstripPath(account, accountPrefController.shareFolderValue),
).listen(
(ev) {
results = ev;

View file

@ -22,7 +22,8 @@ class MetadataController {
required this.prefController,
}) {
_subscriptions.add(filesController.stream.listen(_onFilesEvent));
_subscriptions.add(prefController.isEnableExif.listen(_onSetEnableExif));
_subscriptions
.add(prefController.isEnableExifChange.listen(_onSetEnableExif));
}
void dispose() {
@ -39,7 +40,7 @@ class MetadataController {
Future<void> _onFilesEvent(FilesStreamEvent ev) async {
_log.info("[_onFilesEvent]");
if (!prefController.isEnableExif.value) {
if (!prefController.isEnableExifValue) {
// disabled
return;
}

View file

@ -71,7 +71,7 @@ class PersonsController {
_personStreamContorller.add(lastData);
final completer = Completer();
ListPerson(_c.withLocalRepo())(
account, accountPrefController.personProvider.value)
account, accountPrefController.personProviderValue)
.listen(
(results) {
lastData = PersonStreamEvent(

View file

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/pref.dart';
import 'package:nc_photos/language_util.dart' as language_util;
import 'package:nc_photos/language_util.dart';
import 'package:nc_photos/object_extension.dart';
import 'package:nc_photos/size.dart';
import 'package:np_codegen/np_codegen.dart';
@ -14,134 +14,94 @@ import 'package:rxdart/rxdart.dart';
part 'pref_controller.g.dart';
@npLog
@npSubjectAccessor
class PrefController {
PrefController(this._c);
ValueStream<language_util.AppLanguage> get language =>
_languageController.stream;
Future<void> setAppLanguage(language_util.AppLanguage value) =>
_set<language_util.AppLanguage>(
Future<void> setAppLanguage(AppLanguage value) => _set<AppLanguage>(
controller: _languageController,
setter: (pref, value) => pref.setLanguage(value.langId),
value: value,
);
ValueStream<int> get homePhotosZoomLevel =>
_homePhotosZoomLevelController.stream;
Future<void> setHomePhotosZoomLevel(int value) => _set<int>(
controller: _homePhotosZoomLevelController,
setter: (pref, value) => pref.setHomePhotosZoomLevel(value),
value: value,
);
ValueStream<int> get albumBrowserZoomLevel =>
_albumBrowserZoomLevelController.stream;
Future<void> setAlbumBrowserZoomLevel(int value) => _set<int>(
controller: _albumBrowserZoomLevelController,
setter: (pref, value) => pref.setAlbumBrowserZoomLevel(value),
value: value,
);
ValueStream<int> get homeAlbumsSort => _homeAlbumsSortController.stream;
Future<void> setHomeAlbumsSort(int value) => _set<int>(
controller: _homeAlbumsSortController,
setter: (pref, value) => pref.setHomeAlbumsSort(value),
value: value,
);
ValueStream<bool> get isEnableExif => _isEnableExifController.stream;
Future<void> setEnableExif(bool value) => _set<bool>(
controller: _isEnableExifController,
setter: (pref, value) => pref.setEnableExif(value),
value: value,
);
ValueStream<bool> get shouldProcessExifWifiOnly =>
_shouldProcessExifWifiOnlyController.stream;
Future<void> setProcessExifWifiOnly(bool value) => _set<bool>(
controller: _shouldProcessExifWifiOnlyController,
setter: (pref, value) => pref.setProcessExifWifiOnly(value),
value: value,
);
ValueStream<int> get memoriesRange => _memoriesRangeController.stream;
Future<void> setMemoriesRange(int value) => _set<int>(
controller: _memoriesRangeController,
setter: (pref, value) => pref.setMemoriesRange(value),
value: value,
);
ValueStream<bool> get isPhotosTabSortByName =>
_isPhotosTabSortByNameController.stream;
Future<void> setPhotosTabSortByName(bool value) => _set<bool>(
controller: _isPhotosTabSortByNameController,
setter: (pref, value) => pref.setPhotosTabSortByName(value),
value: value,
);
ValueStream<int> get viewerScreenBrightness =>
_viewerScreenBrightnessController.stream;
Future<void> setViewerScreenBrightness(int value) => _set<int>(
controller: _viewerScreenBrightnessController,
setter: (pref, value) => pref.setViewerScreenBrightness(value),
value: value,
);
ValueStream<bool> get isViewerForceRotation =>
_isViewerForceRotationController.stream;
Future<void> setViewerForceRotation(bool value) => _set<bool>(
controller: _isViewerForceRotationController,
setter: (pref, value) => pref.setViewerForceRotation(value),
value: value,
);
ValueStream<GpsMapProvider> get gpsMapProvider =>
_gpsMapProviderController.stream;
Future<void> setGpsMapProvider(GpsMapProvider value) => _set<GpsMapProvider>(
controller: _gpsMapProviderController,
setter: (pref, value) => pref.setGpsMapProvider(value.index),
value: value,
);
ValueStream<bool> get isAlbumBrowserShowDate =>
_isAlbumBrowserShowDateController.stream;
Future<void> setAlbumBrowserShowDate(bool value) => _set<bool>(
controller: _isAlbumBrowserShowDateController,
setter: (pref, value) => pref.setAlbumBrowserShowDate(value),
value: value,
);
ValueStream<bool> get isDoubleTapExit => _isDoubleTapExitController.stream;
Future<void> setDoubleTapExit(bool value) => _set<bool>(
controller: _isDoubleTapExitController,
setter: (pref, value) => pref.setDoubleTapExit(value),
value: value,
);
ValueStream<bool> get isSaveEditResultToServer =>
_isSaveEditResultToServerController.stream;
Future<void> setSaveEditResultToServer(bool value) => _set<bool>(
controller: _isSaveEditResultToServerController,
setter: (pref, value) => pref.setSaveEditResultToServer(value),
value: value,
);
ValueStream<SizeInt> get enhanceMaxSize => _enhanceMaxSizeController.stream;
Future<void> setEnhanceMaxSize(SizeInt value) => _set<SizeInt>(
controller: _enhanceMaxSizeController,
setter: (pref, value) async {
@ -154,34 +114,24 @@ class PrefController {
value: value,
);
ValueStream<bool> get isDarkTheme => _isDarkThemeController.stream;
Future<void> setDarkTheme(bool value) => _set<bool>(
controller: _isDarkThemeController,
setter: (pref, value) => pref.setDarkTheme(value),
value: value,
);
ValueStream<bool> get isFollowSystemTheme =>
_isFollowSystemThemeController.stream;
Future<void> setFollowSystemTheme(bool value) => _set<bool>(
controller: _isFollowSystemThemeController,
setter: (pref, value) => pref.setFollowSystemTheme(value),
value: value,
);
ValueStream<bool> get isUseBlackInDarkTheme =>
_isUseBlackInDarkThemeController.stream;
Future<void> setUseBlackInDarkTheme(bool value) => _set<bool>(
controller: _isUseBlackInDarkThemeController,
setter: (pref, value) => pref.setUseBlackInDarkTheme(value),
value: value,
);
ValueStream<Color?> get seedColor => _seedColorController.stream;
Future<void> setSeedColor(Color? value) => _setOrRemove<Color>(
controller: _seedColorController,
setter: (pref, value) => pref.setSeedColor(value.withAlpha(0xFF).value),
@ -235,51 +185,70 @@ class PrefController {
}
}
static language_util.AppLanguage _langIdToAppLanguage(int langId) {
static AppLanguage _langIdToAppLanguage(int langId) {
try {
return language_util.supportedLanguages[langId]!;
return supportedLanguages[langId]!;
} catch (_) {
return language_util.supportedLanguages[0]!;
return supportedLanguages[0]!;
}
}
final DiContainer _c;
@npSubjectAccessor
late final _languageController =
BehaviorSubject.seeded(_langIdToAppLanguage(_c.pref.getLanguageOr(0)));
@npSubjectAccessor
late final _homePhotosZoomLevelController =
BehaviorSubject.seeded(_c.pref.getHomePhotosZoomLevelOr(0));
@npSubjectAccessor
late final _albumBrowserZoomLevelController =
BehaviorSubject.seeded(_c.pref.getAlbumBrowserZoomLevelOr(0));
@npSubjectAccessor
late final _homeAlbumsSortController =
BehaviorSubject.seeded(_c.pref.getHomeAlbumsSortOr(0));
@npSubjectAccessor
late final _isEnableExifController =
BehaviorSubject.seeded(_c.pref.isEnableExifOr(true));
@npSubjectAccessor
late final _shouldProcessExifWifiOnlyController =
BehaviorSubject.seeded(_c.pref.shouldProcessExifWifiOnlyOr(true));
@npSubjectAccessor
late final _memoriesRangeController =
BehaviorSubject.seeded(_c.pref.getMemoriesRangeOr(2));
@npSubjectAccessor
late final _isPhotosTabSortByNameController =
BehaviorSubject.seeded(_c.pref.isPhotosTabSortByNameOr(false));
@npSubjectAccessor
late final _viewerScreenBrightnessController =
BehaviorSubject.seeded(_c.pref.getViewerScreenBrightnessOr(-1));
@npSubjectAccessor
late final _isViewerForceRotationController =
BehaviorSubject.seeded(_c.pref.isViewerForceRotationOr(false));
@npSubjectAccessor
late final _gpsMapProviderController = BehaviorSubject.seeded(
GpsMapProvider.values[_c.pref.getGpsMapProviderOr(0)]);
@npSubjectAccessor
late final _isAlbumBrowserShowDateController =
BehaviorSubject.seeded(_c.pref.isAlbumBrowserShowDateOr(false));
@npSubjectAccessor
late final _isDoubleTapExitController =
BehaviorSubject.seeded(_c.pref.isDoubleTapExitOr(false));
@npSubjectAccessor
late final _isSaveEditResultToServerController =
BehaviorSubject.seeded(_c.pref.isSaveEditResultToServerOr(true));
@npSubjectAccessor
late final _enhanceMaxSizeController = BehaviorSubject.seeded(
SizeInt(_c.pref.getEnhanceMaxWidthOr(), _c.pref.getEnhanceMaxHeightOr()));
@npSubjectAccessor
late final _isDarkThemeController =
BehaviorSubject.seeded(_c.pref.isDarkThemeOr(false));
@npSubjectAccessor
late final _isFollowSystemThemeController =
BehaviorSubject.seeded(_c.pref.isFollowSystemThemeOr(false));
@npSubjectAccessor
late final _isUseBlackInDarkThemeController =
BehaviorSubject.seeded(_c.pref.isUseBlackInDarkThemeOr(false));
@NpSubjectAccessor(type: "Color?")
late final _seedColorController =
BehaviorSubject<Color?>.seeded(_c.pref.getSeedColor()?.run(Color.new));
}

View file

@ -12,3 +12,133 @@ extension _$PrefControllerNpLog on PrefController {
static final log = Logger("controller.pref_controller.PrefController");
}
// **************************************************************************
// NpSubjectAccessorGenerator
// **************************************************************************
extension $PrefControllerNpSubjectAccessor on PrefController {
// _languageController
ValueStream<AppLanguage> get language => _languageController.stream;
Stream<AppLanguage> get languageNew => language.skip(1);
Stream<AppLanguage> get languageChange => language.distinct().skip(1);
AppLanguage get languageValue => _languageController.value;
// _homePhotosZoomLevelController
ValueStream<int> get homePhotosZoomLevel =>
_homePhotosZoomLevelController.stream;
Stream<int> get homePhotosZoomLevelNew => homePhotosZoomLevel.skip(1);
Stream<int> get homePhotosZoomLevelChange =>
homePhotosZoomLevel.distinct().skip(1);
int get homePhotosZoomLevelValue => _homePhotosZoomLevelController.value;
// _albumBrowserZoomLevelController
ValueStream<int> get albumBrowserZoomLevel =>
_albumBrowserZoomLevelController.stream;
Stream<int> get albumBrowserZoomLevelNew => albumBrowserZoomLevel.skip(1);
Stream<int> get albumBrowserZoomLevelChange =>
albumBrowserZoomLevel.distinct().skip(1);
int get albumBrowserZoomLevelValue => _albumBrowserZoomLevelController.value;
// _homeAlbumsSortController
ValueStream<int> get homeAlbumsSort => _homeAlbumsSortController.stream;
Stream<int> get homeAlbumsSortNew => homeAlbumsSort.skip(1);
Stream<int> get homeAlbumsSortChange => homeAlbumsSort.distinct().skip(1);
int get homeAlbumsSortValue => _homeAlbumsSortController.value;
// _isEnableExifController
ValueStream<bool> get isEnableExif => _isEnableExifController.stream;
Stream<bool> get isEnableExifNew => isEnableExif.skip(1);
Stream<bool> get isEnableExifChange => isEnableExif.distinct().skip(1);
bool get isEnableExifValue => _isEnableExifController.value;
// _shouldProcessExifWifiOnlyController
ValueStream<bool> get shouldProcessExifWifiOnly =>
_shouldProcessExifWifiOnlyController.stream;
Stream<bool> get shouldProcessExifWifiOnlyNew =>
shouldProcessExifWifiOnly.skip(1);
Stream<bool> get shouldProcessExifWifiOnlyChange =>
shouldProcessExifWifiOnly.distinct().skip(1);
bool get shouldProcessExifWifiOnlyValue =>
_shouldProcessExifWifiOnlyController.value;
// _memoriesRangeController
ValueStream<int> get memoriesRange => _memoriesRangeController.stream;
Stream<int> get memoriesRangeNew => memoriesRange.skip(1);
Stream<int> get memoriesRangeChange => memoriesRange.distinct().skip(1);
int get memoriesRangeValue => _memoriesRangeController.value;
// _isPhotosTabSortByNameController
ValueStream<bool> get isPhotosTabSortByName =>
_isPhotosTabSortByNameController.stream;
Stream<bool> get isPhotosTabSortByNameNew => isPhotosTabSortByName.skip(1);
Stream<bool> get isPhotosTabSortByNameChange =>
isPhotosTabSortByName.distinct().skip(1);
bool get isPhotosTabSortByNameValue => _isPhotosTabSortByNameController.value;
// _viewerScreenBrightnessController
ValueStream<int> get viewerScreenBrightness =>
_viewerScreenBrightnessController.stream;
Stream<int> get viewerScreenBrightnessNew => viewerScreenBrightness.skip(1);
Stream<int> get viewerScreenBrightnessChange =>
viewerScreenBrightness.distinct().skip(1);
int get viewerScreenBrightnessValue =>
_viewerScreenBrightnessController.value;
// _isViewerForceRotationController
ValueStream<bool> get isViewerForceRotation =>
_isViewerForceRotationController.stream;
Stream<bool> get isViewerForceRotationNew => isViewerForceRotation.skip(1);
Stream<bool> get isViewerForceRotationChange =>
isViewerForceRotation.distinct().skip(1);
bool get isViewerForceRotationValue => _isViewerForceRotationController.value;
// _gpsMapProviderController
ValueStream<GpsMapProvider> get gpsMapProvider =>
_gpsMapProviderController.stream;
Stream<GpsMapProvider> get gpsMapProviderNew => gpsMapProvider.skip(1);
Stream<GpsMapProvider> get gpsMapProviderChange =>
gpsMapProvider.distinct().skip(1);
GpsMapProvider get gpsMapProviderValue => _gpsMapProviderController.value;
// _isAlbumBrowserShowDateController
ValueStream<bool> get isAlbumBrowserShowDate =>
_isAlbumBrowserShowDateController.stream;
Stream<bool> get isAlbumBrowserShowDateNew => isAlbumBrowserShowDate.skip(1);
Stream<bool> get isAlbumBrowserShowDateChange =>
isAlbumBrowserShowDate.distinct().skip(1);
bool get isAlbumBrowserShowDateValue =>
_isAlbumBrowserShowDateController.value;
// _isDoubleTapExitController
ValueStream<bool> get isDoubleTapExit => _isDoubleTapExitController.stream;
Stream<bool> get isDoubleTapExitNew => isDoubleTapExit.skip(1);
Stream<bool> get isDoubleTapExitChange => isDoubleTapExit.distinct().skip(1);
bool get isDoubleTapExitValue => _isDoubleTapExitController.value;
// _isSaveEditResultToServerController
ValueStream<bool> get isSaveEditResultToServer =>
_isSaveEditResultToServerController.stream;
Stream<bool> get isSaveEditResultToServerNew =>
isSaveEditResultToServer.skip(1);
Stream<bool> get isSaveEditResultToServerChange =>
isSaveEditResultToServer.distinct().skip(1);
bool get isSaveEditResultToServerValue =>
_isSaveEditResultToServerController.value;
// _enhanceMaxSizeController
ValueStream<SizeInt> get enhanceMaxSize => _enhanceMaxSizeController.stream;
Stream<SizeInt> get enhanceMaxSizeNew => enhanceMaxSize.skip(1);
Stream<SizeInt> get enhanceMaxSizeChange => enhanceMaxSize.distinct().skip(1);
SizeInt get enhanceMaxSizeValue => _enhanceMaxSizeController.value;
// _isDarkThemeController
ValueStream<bool> get isDarkTheme => _isDarkThemeController.stream;
Stream<bool> get isDarkThemeNew => isDarkTheme.skip(1);
Stream<bool> get isDarkThemeChange => isDarkTheme.distinct().skip(1);
bool get isDarkThemeValue => _isDarkThemeController.value;
// _isFollowSystemThemeController
ValueStream<bool> get isFollowSystemTheme =>
_isFollowSystemThemeController.stream;
Stream<bool> get isFollowSystemThemeNew => isFollowSystemTheme.skip(1);
Stream<bool> get isFollowSystemThemeChange =>
isFollowSystemTheme.distinct().skip(1);
bool get isFollowSystemThemeValue => _isFollowSystemThemeController.value;
// _isUseBlackInDarkThemeController
ValueStream<bool> get isUseBlackInDarkTheme =>
_isUseBlackInDarkThemeController.stream;
Stream<bool> get isUseBlackInDarkThemeNew => isUseBlackInDarkTheme.skip(1);
Stream<bool> get isUseBlackInDarkThemeChange =>
isUseBlackInDarkTheme.distinct().skip(1);
bool get isUseBlackInDarkThemeValue => _isUseBlackInDarkThemeController.value;
// _seedColorController
ValueStream<Color?> get seedColor => _seedColorController.stream;
Stream<Color?> get seedColorNew => seedColor.skip(1);
Stream<Color?> get seedColorChange => seedColor.distinct().skip(1);
Color? get seedColorValue => _seedColorController.value;
}

View file

@ -112,7 +112,7 @@ ThemeData buildDarkTheme(BuildContext context, [ColorScheme? dynamicScheme]) {
}
Color? getSeedColor(BuildContext context) {
return context.read<PrefController>().seedColor.value;
return context.read<PrefController>().seedColorValue;
}
ColorScheme _getColorScheme(

View file

@ -7,7 +7,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
required this.controller,
required this.prefController,
}) : super(_State.init(
zoom: prefController.albumBrowserZoomLevel.value,
zoom: prefController.albumBrowserZoomLevelValue,
)) {
on<_LoadItems>(_onLoad);
on<_TransformItems>(_onTransformItems);

View file

@ -15,7 +15,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
super(_State.init(
collection: collection,
coverUrl: _getCoverUrl(collection),
zoom: prefController.albumBrowserZoomLevel.value,
zoom: prefController.albumBrowserZoomLevelValue,
)) {
_initItemController(collection);

View file

@ -102,8 +102,8 @@ class _EditContentList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<int>(
stream: context.read<PrefController>().albumBrowserZoomLevel,
initialData: context.read<PrefController>().albumBrowserZoomLevel.value,
stream: context.read<PrefController>().albumBrowserZoomLevelChange,
initialData: context.read<PrefController>().albumBrowserZoomLevelValue,
builder: (_, zoomLevel) {
if (zoomLevel.hasError) {
context.addEvent(
@ -159,9 +159,9 @@ class _UnmodifiableEditContentList extends StatelessWidget {
sliver: SliverOpacity(
opacity: .25,
sliver: StreamBuilder<int>(
stream: context.read<PrefController>().albumBrowserZoomLevel,
stream: context.read<PrefController>().albumBrowserZoomLevelChange,
initialData:
context.read<PrefController>().albumBrowserZoomLevel.value,
context.read<PrefController>().albumBrowserZoomLevelValue,
builder: (_, zoomLevel) {
if (zoomLevel.hasError) {
context.addEvent(_SetMessage(

View file

@ -8,6 +8,7 @@ import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/app_localizations.dart';
import 'package:nc_photos/controller/account_controller.dart';
import 'package:nc_photos/controller/account_pref_controller.dart';
import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/album.dart';
import 'package:nc_photos/entity/album/data_source.dart';
@ -187,8 +188,7 @@ class _HomeState extends State<Home> with TickerProviderStateMixin {
context
.read<AccountController>()
.accountPrefController
.shareFolder
.value,
.shareFolderValue,
);
} catch (e, stacktrace) {
_log.shout(

View file

@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/api/api_util.dart' as api_util;
import 'package:nc_photos/controller/account_controller.dart';
import 'package:nc_photos/controller/account_pref_controller.dart';
import 'package:nc_photos/stream_util.dart';
import 'package:nc_photos/theme.dart';
import 'package:nc_photos/widget/account_picker_dialog.dart';

View file

@ -20,7 +20,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
on<_SetError>(_onSetError);
_subscriptions.add(prefController.homeAlbumsSort.distinct().listen((event) {
_subscriptions.add(prefController.homeAlbumsSortChange.listen((event) {
add(_UpdateCollectionSort(collection_util.CollectionSort.values[event]));
}));
_subscriptions.add(controller.stream.listen((event) {

View file

@ -13,9 +13,9 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
required this.personsController,
required this.metadataController,
}) : super(_State.init(
zoom: prefController.homePhotosZoomLevel.value,
zoom: prefController.homePhotosZoomLevelValue,
isEnableMemoryCollection:
accountPrefController.isEnableMemoryAlbum.value,
accountPrefController.isEnableMemoryAlbumValue,
)) {
on<_LoadItems>(_onLoad);
on<_RequestRefresh>(_onRequestRefresh);
@ -46,13 +46,14 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
on<_SetError>(_onSetError);
_subscriptions
.add(accountPrefController.isEnableMemoryAlbum.listen((event) {
.add(accountPrefController.isEnableMemoryAlbumChange.listen((event) {
add(_SetEnableMemoryCollection(event));
}));
_subscriptions.add(prefController.isPhotosTabSortByName.listen((event) {
_subscriptions
.add(prefController.isPhotosTabSortByNameChange.listen((event) {
add(_SetSortByName(event));
}));
_subscriptions.add(prefController.memoriesRange.listen((event) {
_subscriptions.add(prefController.memoriesRangeChange.listen((event) {
add(_SetMemoriesRange(event));
}));
}
@ -138,7 +139,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
account: account,
filesController: controller,
personsController: personsController,
personProvider: accountPrefController.personProvider.value,
personProvider: accountPrefController.personProviderValue,
);
}
@ -303,11 +304,11 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_ItemTransformerArgument(
account: account,
files: files,
sort: prefController.isPhotosTabSortByName.value
sort: prefController.isPhotosTabSortByNameValue
? _ItemSort.filename
: _ItemSort.dateTime,
isGroupByDay: prefController.homePhotosZoomLevel.value >= 0,
memoriesDayRange: prefController.memoriesRange.value,
isGroupByDay: prefController.homePhotosZoomLevelValue >= 0,
memoriesDayRange: prefController.memoriesRangeValue,
locale: language_util.getSelectedLocale() ??
PlatformDispatcher.instance.locale,
),

View file

@ -5,11 +5,11 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc({
required this.prefController,
}) : super(_State(
language: prefController.language.value,
isDarkTheme: prefController.isDarkTheme.value,
isFollowSystemTheme: prefController.isFollowSystemTheme.value,
isUseBlackInDarkTheme: prefController.isUseBlackInDarkTheme.value,
seedColor: prefController.seedColor.value?.value,
language: prefController.languageValue,
isDarkTheme: prefController.isDarkThemeValue,
isFollowSystemTheme: prefController.isFollowSystemThemeValue,
isUseBlackInDarkTheme: prefController.isUseBlackInDarkThemeValue,
seedColor: prefController.seedColorValue?.value,
)) {
on<_Init>(_onInit);
}
@ -21,23 +21,23 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_log.info(ev);
await Future.wait([
emit.forEachIgnoreError<language_util.AppLanguage>(
prefController.language,
prefController.languageChange,
onData: (data) => state.copyWith(language: data),
),
emit.forEachIgnoreError<bool>(
prefController.isDarkTheme,
prefController.isDarkThemeChange,
onData: (data) => state.copyWith(isDarkTheme: data),
),
emit.forEachIgnoreError<bool>(
prefController.isFollowSystemTheme,
prefController.isFollowSystemThemeChange,
onData: (data) => state.copyWith(isFollowSystemTheme: data),
),
emit.forEachIgnoreError<bool>(
prefController.isUseBlackInDarkTheme,
prefController.isUseBlackInDarkThemeChange,
onData: (data) => state.copyWith(isUseBlackInDarkTheme: data),
),
emit.forEachIgnoreError<Color?>(
prefController.seedColor,
prefController.seedColorChange,
onData: (data) => state.copyWith(seedColor: data?.value),
),
]);

View file

@ -9,6 +9,7 @@ import 'package:nc_photos/account.dart';
import 'package:nc_photos/app_localizations.dart';
import 'package:nc_photos/bloc_util.dart';
import 'package:nc_photos/controller/account_controller.dart';
import 'package:nc_photos/controller/account_pref_controller.dart';
import 'package:nc_photos/controller/persons_controller.dart';
import 'package:nc_photos/controller/places_controller.dart';
import 'package:nc_photos/entity/collection/builder.dart';

View file

@ -10,13 +10,13 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
}) : _c = container,
super(_State.init(
account: account,
label: accountPrefController.accountLabel.value,
shareFolder: accountPrefController.shareFolder.value,
personProvider: accountPrefController.personProvider.value,
label: accountPrefController.accountLabelValue,
shareFolder: accountPrefController.shareFolderValue,
personProvider: accountPrefController.personProviderValue,
)) {
on<_SetLabel>(_onSetLabel);
on<_OnUpdateLabel>(_onOnUpdateLabel);
_subscriptions.add(accountPrefController.accountLabel.listen(
_subscriptions.add(accountPrefController.accountLabelChange.listen(
(event) {
add(_OnUpdateLabel(event));
},
@ -30,7 +30,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
on<_SetShareFolder>(_onSetShareFolder);
on<_OnUpdateShareFolder>(_onOnUpdateShareFolder);
_subscriptions.add(accountPrefController.shareFolder.listen(
_subscriptions.add(accountPrefController.shareFolderChange.listen(
(event) {
add(_OnUpdateShareFolder(event));
},
@ -41,7 +41,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
on<_SetPersonProvider>(_onSetPersonProvider);
on<_OnUpdatePersonProvider>(_onOnUpdatePersonProvider);
_subscriptions.add(accountPrefController.personProvider.listen(
_subscriptions.add(accountPrefController.personProviderChange.listen(
(event) {
add(_OnUpdatePersonProvider(event));
},

View file

@ -5,7 +5,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc({
required this.prefController,
}) : super(_State(
isBrowserShowDate: prefController.isAlbumBrowserShowDate.value,
isBrowserShowDate: prefController.isAlbumBrowserShowDateValue,
)) {
on<_Init>(_onInit);
on<_SetBrowserShowDate>(_onSetBrowserShowDate);
@ -17,7 +17,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
Future<void> _onInit(_Init ev, Emitter<_State> emit) async {
_log.info(ev);
return emit.forEach<bool>(
prefController.isAlbumBrowserShowDate,
prefController.isAlbumBrowserShowDateChange,
onData: (data) => state.copyWith(isBrowserShowDate: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);

View file

@ -6,8 +6,8 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
required this.prefController,
}) : super(_State(
isSaveEditResultToServer:
prefController.isSaveEditResultToServer.value,
maxSize: prefController.enhanceMaxSize.value,
prefController.isSaveEditResultToServerValue,
maxSize: prefController.enhanceMaxSizeValue,
)) {
on<_Init>(_onInit);
on<_SetSaveEditResultToServer>(_onSetSaveEditResultToServer);
@ -21,7 +21,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_log.info(ev);
await Future.wait([
emit.forEach<bool>(
prefController.isSaveEditResultToServer,
prefController.isSaveEditResultToServerChange,
onData: (data) => state.copyWith(isSaveEditResultToServer: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
@ -29,7 +29,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
},
),
emit.forEach<SizeInt>(
prefController.enhanceMaxSize,
prefController.enhanceMaxSizeChange,
onData: (data) => state.copyWith(maxSize: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);

View file

@ -5,7 +5,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc({
required this.prefController,
}) : super(_State.init(
selected: prefController.language.value,
selected: prefController.languageValue,
)) {
on<_Init>(_onInit);
on<_SelectLanguage>(_onSelectLanguage);
@ -31,10 +31,8 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
Future<void> _onInit(_Init ev, Emitter<_State> emit) {
_log.info(ev);
return emit.forEach<language_util.AppLanguage>(
prefController.language,
onData: (data) => state.copyWith(
selected: data,
),
prefController.languageChange,
onData: (data) => state.copyWith(selected: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
return state.copyWith(

View file

@ -5,8 +5,8 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc({
required this.prefController,
}) : super(_State(
isEnable: prefController.isEnableExif.value,
isWifiOnly: prefController.shouldProcessExifWifiOnly.value,
isEnable: prefController.isEnableExifValue,
isWifiOnly: prefController.shouldProcessExifWifiOnlyValue,
)) {
on<_Init>(_onInit);
on<_SetEnable>(_onSetEnable);
@ -20,7 +20,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_log.info(ev);
await Future.wait([
emit.forEach<bool>(
prefController.isEnableExif,
prefController.isEnableExifChange,
onData: (data) => state.copyWith(isEnable: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
@ -28,7 +28,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
},
),
emit.forEach<bool>(
prefController.shouldProcessExifWifiOnly,
prefController.shouldProcessExifWifiOnlyChange,
onData: (data) => state.copyWith(isWifiOnly: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);

View file

@ -5,8 +5,8 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc({
required this.prefController,
}) : super(_State(
isPhotosTabSortByName: prefController.isPhotosTabSortByName.value,
isDoubleTapExit: prefController.isDoubleTapExit.value,
isPhotosTabSortByName: prefController.isPhotosTabSortByNameValue,
isDoubleTapExit: prefController.isDoubleTapExitValue,
)) {
on<_Init>(_onInit);
on<_SetPhotosTabSortByName>(_onSetPhotosTabSortByName);
@ -20,7 +20,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_log.info(ev);
await Future.wait([
emit.forEach<bool>(
prefController.isPhotosTabSortByName,
prefController.isPhotosTabSortByNameChange,
onData: (data) => state.copyWith(isPhotosTabSortByName: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
@ -28,7 +28,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
},
),
emit.forEach<bool>(
prefController.isDoubleTapExit,
prefController.isDoubleTapExitChange,
onData: (data) => state.copyWith(isDoubleTapExit: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);

View file

@ -6,9 +6,9 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
required this.prefController,
required this.accountPrefController,
}) : super(_State(
isEnableMemories: accountPrefController.isEnableMemoryAlbum.value,
isPhotosTabSortByName: prefController.isPhotosTabSortByName.value,
memoriesRange: prefController.memoriesRange.value,
isEnableMemories: accountPrefController.isEnableMemoryAlbumValue,
isPhotosTabSortByName: prefController.isPhotosTabSortByNameValue,
memoriesRange: prefController.memoriesRangeValue,
)) {
on<_Init>(_onInit);
on<_SetEnableMemories>(_onSetEnableMemories);
@ -22,7 +22,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_log.info(ev);
await Future.wait([
emit.forEach<bool>(
accountPrefController.isEnableMemoryAlbum,
accountPrefController.isEnableMemoryAlbumChange,
onData: (data) => state.copyWith(isEnableMemories: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
@ -30,7 +30,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
},
),
emit.forEach<bool>(
prefController.isPhotosTabSortByName,
prefController.isPhotosTabSortByNameChange,
onData: (data) => state.copyWith(isPhotosTabSortByName: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
@ -38,7 +38,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
},
),
emit.forEach<int>(
prefController.memoriesRange,
prefController.memoriesRangeChange,
onData: (data) => state.copyWith(memoriesRange: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);

View file

@ -5,9 +5,9 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc({
required this.prefController,
}) : super(_State(
isFollowSystemTheme: prefController.isFollowSystemTheme.value,
isUseBlackInDarkTheme: prefController.isUseBlackInDarkTheme.value,
seedColor: prefController.seedColor.value?.value,
isFollowSystemTheme: prefController.isFollowSystemThemeValue,
isUseBlackInDarkTheme: prefController.isUseBlackInDarkThemeValue,
seedColor: prefController.seedColorValue?.value,
)) {
on<_Init>(_onInit);
on<_SetFollowSystemTheme>(_onSetFollowSystemTheme);
@ -22,7 +22,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_log.info(ev);
await Future.wait([
emit.forEach<bool>(
prefController.isFollowSystemTheme,
prefController.isFollowSystemThemeChange,
onData: (data) => state.copyWith(isFollowSystemTheme: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
@ -30,7 +30,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
},
),
emit.forEach<bool>(
prefController.isUseBlackInDarkTheme,
prefController.isUseBlackInDarkThemeChange,
onData: (data) => state.copyWith(isUseBlackInDarkTheme: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
@ -38,7 +38,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
},
),
emit.forEach<Color?>(
prefController.seedColor,
prefController.seedColorChange,
onData: (data) => state.copyWith(seedColor: data?.value),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);

View file

@ -5,9 +5,9 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc({
required this.prefController,
}) : super(_State(
screenBrightness: prefController.viewerScreenBrightness.value,
isForceRotation: prefController.isViewerForceRotation.value,
gpsMapProvider: prefController.gpsMapProvider.value,
screenBrightness: prefController.viewerScreenBrightnessValue,
isForceRotation: prefController.isViewerForceRotationValue,
gpsMapProvider: prefController.gpsMapProviderValue,
)) {
on<_Init>(_onInit);
on<_SetScreenBrightness>(_onSetScreenBrightness);
@ -22,7 +22,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_log.info(ev);
await Future.wait([
emit.forEach<int>(
prefController.viewerScreenBrightness,
prefController.viewerScreenBrightnessChange,
onData: (data) => state.copyWith(screenBrightness: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
@ -30,7 +30,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
},
),
emit.forEach<bool>(
prefController.isViewerForceRotation,
prefController.isViewerForceRotationChange,
onData: (data) => state.copyWith(isForceRotation: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
@ -38,7 +38,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
},
),
emit.forEach<GpsMapProvider>(
prefController.gpsMapProvider,
prefController.gpsMapProviderChange,
onData: (data) => state.copyWith(gpsMapProvider: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);

View file

@ -70,7 +70,7 @@ class _Bloc extends Bloc<_Event, _State> {
);
try {
return await ImportPotentialSharedAlbum(c)(
account, accountPrefController.shareFolder.value);
account, accountPrefController.shareFolderValue);
} catch (e, stackTrace) {
_log.shout(
"[_importPotentialSharedAlbum] Failed while ImportPotentialSharedAlbum",

View file

@ -2,3 +2,4 @@ library np_codegen;
export 'src/drift_table_sort_annotations.dart';
export 'src/np_log_annotations.dart';
export 'src/np_subject_accessor_annotations.dart';

View file

@ -0,0 +1,9 @@
class NpSubjectAccessor {
const NpSubjectAccessor({
this.type,
});
final String? type;
}
const npSubjectAccessor = NpSubjectAccessor();

View file

@ -1,7 +1,7 @@
builders:
np_log_build:
import: "package:np_codegen_build/builder.dart"
builder_factories: ["driftTableSortBuilder", "npLogBuilder"]
builder_factories: ["driftTableSortBuilder", "npLogBuilder", "npSubjectAccessorBuilder"]
# The `partId` argument to `SharedPartBuilder` is "some_cool_builder"
build_extensions: {".dart": [".np_codegen.g.part"]}
auto_apply: dependents

View file

@ -1,6 +1,7 @@
import 'package:build/build.dart';
import 'package:np_codegen_build/src/drift_table_sort_generator.dart';
import 'package:np_codegen_build/src/np_log_generator.dart';
import 'package:np_codegen_build/src/np_subject_accessor_generator.dart';
import 'package:source_gen/source_gen.dart';
Builder driftTableSortBuilder(BuilderOptions options) =>
@ -8,3 +9,6 @@ Builder driftTableSortBuilder(BuilderOptions options) =>
Builder npLogBuilder(BuilderOptions options) =>
SharedPartBuilder([const NpLogGenerator()], "np_log");
Builder npSubjectAccessorBuilder(BuilderOptions options) => SharedPartBuilder(
[const NpSubjectAccessorGenerator()], "np_subject_accessor");

View file

@ -0,0 +1,132 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:np_codegen/np_codegen.dart';
import 'package:source_gen/source_gen.dart';
class NpSubjectAccessorGenerator
extends GeneratorForAnnotation<NpSubjectAccessor> {
const NpSubjectAccessorGenerator();
@override
Future<String?> generateForAnnotatedElement(
Element element,
ConstantReader annotation,
BuildStep buildStep,
) async {
if (element is! ClassElement) {
// not class, probably field
return null;
}
final clazz = element;
final fields = await _getFields(buildStep.resolver, clazz);
return """
extension \$${clazz.name}NpSubjectAccessor on ${clazz.name} {
${_buildBody(fields)}
}
""";
}
String _buildBody(List<_FieldMeta> fields) {
final results = <String>[];
for (final f in fields) {
results
..add("// ${f.fullname}")
..add(
"ValueStream<${f.typeStr}> get ${f.name} => ${f.fullname}.stream;")
..add("Stream<${f.typeStr}> get ${f.name}New => ${f.name}.skip(1);")
..add(
"Stream<${f.typeStr}> get ${f.name}Change => ${f.name}.distinct().skip(1);")
..add("${f.typeStr} get ${f.name}Value => ${f.fullname}.value;");
}
return results.join("\n");
}
Future<List<_FieldMeta>> _getFields(
Resolver resolver, ClassElement clazz) async {
const typeChecker = TypeChecker.fromRuntime(NpSubjectAccessor);
final data = <_FieldMeta>[];
for (final f in clazz.fields.where(typeChecker.hasAnnotationOf)) {
// final annotation = typeChecker.annotationsOf(f).first;
// final type = annotation.getField("type")!.toTypeValue()!;
final parseName = _parseName(f);
final parseType = await _parseTypeString(resolver, f);
data.add(_FieldMeta(
name: parseName.name,
fullname: parseName.fullname,
typeStr: parseType.typeStr,
));
}
return data;
}
_NameParseResult _parseName(FieldElement field) {
var name = field.name;
if (name.startsWith("_")) {
name = name.substring(1);
}
if (name.endsWith("Controller")) {
name = name.substring(0, name.length - 10);
}
return _NameParseResult(name: name, fullname: field.name);
}
Future<_TypeParseResult> _parseTypeString(
Resolver resolver, FieldElement field) async {
String? typeStr;
if (const TypeChecker.fromRuntime(NpSubjectAccessor)
.hasAnnotationOf(field)) {
final annotation = const TypeChecker.fromRuntime(NpSubjectAccessor)
.annotationsOf(field)
.first;
final type = annotation.getField("type")?.toStringValue();
typeStr = type;
}
if (typeStr == null) {
final astNode = await resolver.astNodeFor(field, resolve: true);
typeStr = (astNode! as VariableDeclaration)
.initializer!
.staticType!
.getDisplayString(withNullability: true);
if (typeStr.startsWith("BehaviorSubject<")) {
typeStr = typeStr.substring(16, typeStr.length - 1);
}
if (typeStr == "InvalidType") {
throw UnsupportedError(
"Type can't be parsed, please specify the type in annotation: ${field.name}");
}
}
return _TypeParseResult(typeStr: typeStr);
}
}
class _NameParseResult {
const _NameParseResult({
required this.name,
required this.fullname,
});
final String name;
final String fullname;
}
class _TypeParseResult {
const _TypeParseResult({
required this.typeStr,
});
final String typeStr;
}
class _FieldMeta {
const _FieldMeta({
required this.name,
required this.fullname,
required this.typeStr,
});
final String name;
final String fullname;
final String typeStr;
}

View file

@ -16,12 +16,13 @@ dependencies:
dev_dependencies:
build_test: ^2.1.5
np_lints:
path: ../np_lints
path: any
test: any
code_gen_tester:
git:
url: https://github.com/rrousselGit/functional_widget
ref: v0.10.0
path: packages/code_gen_tester
np_lints:
path: ../np_lints
path: any
rxdart: any
test: any

View file

@ -0,0 +1,117 @@
import 'dart:io';
import 'package:build/build.dart';
import 'package:build_test/build_test.dart';
import 'package:np_codegen_build/src/np_subject_accessor_generator.dart';
import 'package:path/path.dart' as p;
import 'package:source_gen/source_gen.dart';
import 'package:test/test.dart';
void main() {
_resolveCompilationUnit("test/src/np_subject_accessor.dart");
tearDown(() {
// Increment this after each test so the next test has it's own package
_pkgCacheCount++;
});
group("NpSubjectAccessor", () {
test("empty", () async {
final src = _genSrc("""
@npSubjectAccessor
class Empty {}
""");
final expected = _genExpected(r"""
extension $EmptyNpSubjectAccessor on Empty {}
""");
return _buildTest(src, expected);
});
test("int", () async {
final src = _genSrc("""
@npSubjectAccessor
class IntTest {
@npSubjectAccessor
final _barController = BehaviorSubject.seeded(1);
}
""");
final expected = _genExpected(r"""
extension $IntTestNpSubjectAccessor on IntTest {
// _barController
ValueStream<int> get bar => _barController.stream;
Stream<int> get barNew => bar.skip(1);
Stream<int> get barChange => bar.distinct().skip(1);
int get barValue => _barController.value;
}
""");
return _buildTest(src, expected);
});
test("int nullable", () async {
final src = _genSrc("""
@npSubjectAccessor
class IntNullableTest {
@npSubjectAccessor
final _barController = BehaviorSubject<int?>.seeded(1);
}
""");
final expected = _genExpected(r"""
extension $IntNullableTestNpSubjectAccessor on IntNullableTest {
// _barController
ValueStream<int?> get bar => _barController.stream;
Stream<int?> get barNew => bar.skip(1);
Stream<int?> get barChange => bar.distinct().skip(1);
int? get barValue => _barController.value;
}
""");
return _buildTest(src, expected);
});
});
}
String _genSrc(String src) {
return """
import 'package:np_codegen/np_codegen.dart';
import 'package:rxdart/rxdart.dart';
part 'test.g.dart';
$src
""";
}
String _genExpected(String src) {
return """// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'test.dart';
// **************************************************************************
// NpSubjectAccessorGenerator
// **************************************************************************
$src""";
}
Future _buildTest(String src, String expected) {
return testBuilder(
PartBuilder([const NpSubjectAccessorGenerator()], ".g.dart"),
{"$_pkgName|lib/test.dart": src},
generateFor: {'$_pkgName|lib/test.dart'},
outputs: {"$_pkgName|lib/test.g.dart": decodedMatches(expected)},
);
}
// Taken from source_gen_test, unclear why this is needed...
Future<void> _resolveCompilationUnit(String filePath) async {
final assetId = AssetId.parse('a|lib/${p.basename(filePath)}');
final files =
Directory(p.dirname(filePath)).listSync().whereType<File>().toList();
final fileMap = Map<String, String>.fromEntries(files.map(
(f) => MapEntry('a|lib/${p.basename(f.path)}', f.readAsStringSync())));
await resolveSources(fileMap, (item) async {
return await item.libraryFor(assetId);
}, resolverFor: 'a|lib/${p.basename(filePath)}');
}
String get _pkgName => 'pkg$_pkgCacheCount';
int _pkgCacheCount = 1;

View file

@ -0,0 +1,7 @@
// ignore_for_file: unused_import
import 'package:np_codegen/np_codegen.dart';
import 'package:rxdart/rxdart.dart';
@npSubjectAccessor
class Foo {}