albums: case insensitive unique names

This commit is contained in:
Thibault Deckers 2024-04-01 17:04:36 +02:00
parent 1bf5a2e315
commit 08bd187c7d
5 changed files with 26 additions and 7 deletions

View file

@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
- opening app from launcher always show home page - opening app from launcher always show home page
- use dates with western arabic numerals for maghreb arabic locales - use dates with western arabic numerals for maghreb arabic locales
- album unique names are case insensitive
- upgraded Flutter to stable v3.19.5 - upgraded Flutter to stable v3.19.5
### Fixed ### Fixed

View file

@ -196,19 +196,19 @@ mixin AlbumMixin on SourceBase {
final parts = pContext.split(dirPath); final parts = pContext.split(dirPath);
for (var i = parts.length - 1; i > 0; i--) { for (var i = parts.length - 1; i > 0; i--) {
final name = pContext.joinAll(['', ...parts.skip(i)]); final name = pContext.joinAll(['', ...parts.skip(i)]);
final testName = '$separator$name'; final testName = '$separator${name.toLowerCase()}';
if (others.every((item) => !item.endsWith(testName))) return name; if (others.every((item) => !item.endsWith(testName))) return name;
} }
return dirPath; return dirPath;
} }
final otherAlbumsOnDevice = _directories.whereNotNull().where((item) => item != dirPath).toSet(); final otherAlbumsOnDevice = _directories.whereNotNull().where((item) => item != dirPath).map((v) => v.toLowerCase()).toSet();
final uniqueNameInDevice = unique(dirPath, otherAlbumsOnDevice); final uniqueNameInDevice = unique(dirPath, otherAlbumsOnDevice);
if (uniqueNameInDevice.length <= relativeDir.length) { if (uniqueNameInDevice.length <= relativeDir.length) {
return uniqueNameInDevice; return uniqueNameInDevice;
} }
final volumePath = dir.volumePath; final volumePath = dir.volumePath.toLowerCase();
String trimVolumePath(String? path) => path!.substring(dir.volumePath.length); String trimVolumePath(String? path) => path!.substring(dir.volumePath.length);
final otherAlbumsOnVolume = otherAlbumsOnDevice.where((path) => path.startsWith(volumePath)).map(trimVolumePath).toSet(); final otherAlbumsOnVolume = otherAlbumsOnDevice.where((path) => path.startsWith(volumePath)).map(trimVolumePath).toSet();
final uniqueNameInVolume = unique(trimVolumePath(dirPath), otherAlbumsOnVolume); final uniqueNameInVolume = unique(trimVolumePath(dirPath), otherAlbumsOnVolume);

View file

@ -76,7 +76,7 @@ Future<void> _init() async {
enum AnalyzerState { running, stopping, stopped } enum AnalyzerState { running, stopping, stopped }
class Analyzer { class Analyzer with WidgetsBindingObserver {
late AppLocalizations _l10n; late AppLocalizations _l10n;
final ValueNotifier<AnalyzerState> _serviceStateNotifier = ValueNotifier<AnalyzerState>(AnalyzerState.stopped); final ValueNotifier<AnalyzerState> _serviceStateNotifier = ValueNotifier<AnalyzerState>(AnalyzerState.stopped);
AnalysisController? _controller; AnalysisController? _controller;
@ -102,6 +102,7 @@ class Analyzer {
} }
_serviceStateNotifier.addListener(_onServiceStateChanged); _serviceStateNotifier.addListener(_onServiceStateChanged);
_source.stateNotifier.addListener(_onSourceStateChanged); _source.stateNotifier.addListener(_onSourceStateChanged);
WidgetsBinding.instance.addObserver(this);
} }
void dispose() { void dispose() {
@ -111,11 +112,18 @@ class Analyzer {
} }
_stopUpdateTimer(); _stopUpdateTimer();
_controller?.dispose(); _controller?.dispose();
WidgetsBinding.instance.removeObserver(this);
_serviceStateNotifier.removeListener(_onServiceStateChanged); _serviceStateNotifier.removeListener(_onServiceStateChanged);
_source.stateNotifier.removeListener(_onSourceStateChanged); _source.stateNotifier.removeListener(_onSourceStateChanged);
_source.dispose(); _source.dispose();
} }
@override
void didHaveMemoryPressure() {
super.didHaveMemoryPressure();
reportService.log('Analyzer memory pressure');
}
Future<void> start(dynamic args) async { Future<void> start(dynamic args) async {
List<int>? entryIds; List<int>? entryIds;
var force = false; var force = false;
@ -126,7 +134,7 @@ class Analyzer {
progressTotal = args['progressTotal']; progressTotal = args['progressTotal'];
progressOffset = args['progressOffset']; progressOffset = args['progressOffset'];
} }
debugPrint('$runtimeType start for ${entryIds?.length ?? 'all'} entries, at $progressOffset/$progressTotal'); await reportService.log('Analyzer start for ${entryIds?.length ?? 'all'} entries, at $progressOffset/$progressTotal');
_controller?.dispose(); _controller?.dispose();
_controller = AnalysisController( _controller = AnalysisController(
canStartService: false, canStartService: false,
@ -147,8 +155,8 @@ class Analyzer {
}); });
} }
void stop() { Future<void> stop() async {
debugPrint('$runtimeType stop'); await reportService.log('Analyzer stop');
_serviceStateNotifier.value = AnalyzerState.stopped; _serviceStateNotifier.value = AnalyzerState.stopped;
} }

View file

@ -404,6 +404,12 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
} }
} }
@override
void didHaveMemoryPressure() {
super.didHaveMemoryPressure();
reportService.log('App memory pressure');
}
@override @override
void didChangeMetrics() => _updateCutoutInsets(); void didChangeMetrics() => _updateCutoutInsets();

View file

@ -366,6 +366,8 @@ void main() {
FakeMediaStoreService.newImage('${FakeStorageService.removablePath}Marcus Aurelius', '1'), FakeMediaStoreService.newImage('${FakeStorageService.removablePath}Marcus Aurelius', '1'),
FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}Pictures/Hannah Arendt', '1'), FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}Pictures/Hannah Arendt', '1'),
FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}Pictures/Arendt', '1'), FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}Pictures/Arendt', '1'),
FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}Pictures/Something', '1'),
FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}Movies/SomeThing', '1'),
}; };
final source = await _initSource(); final source = await _initSource();
@ -387,6 +389,8 @@ void main() {
expect(source.getAlbumDisplayName(context, '${FakeStorageService.removablePath}Marcus Aurelius'), 'Marcus Aurelius'); expect(source.getAlbumDisplayName(context, '${FakeStorageService.removablePath}Marcus Aurelius'), 'Marcus Aurelius');
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Hannah Arendt'), 'Hannah Arendt'); expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Hannah Arendt'), 'Hannah Arendt');
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Arendt'), 'Arendt'); expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Arendt'), 'Arendt');
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Pictures/Something'), 'Pictures/Something');
expect(source.getAlbumDisplayName(context, '${FakeStorageService.primaryPath}Movies/SomeThing'), 'Movies/SomeThing');
return const Placeholder(); return const Placeholder();
}, },
), ),