1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2024-11-03 21:04:03 +08:00

Merge pull request #862 from sarayourfriend/fix/numerical-file-sort

Trim extensions when sorting filenames
This commit is contained in:
Patrik J. Braun 2024-03-30 19:31:00 +01:00 committed by GitHub
commit 1e0dbc08dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 46 additions and 3 deletions

View File

@ -173,7 +173,7 @@ export class Utils {
}
static getOffsetMinutes(offsetString: string) { //Convert offset string (+HH:MM or -HH:MM) into a minute value
const regex = /^([+-](0[0-9]|1[0-4]):[0-5][0-9])$/; //checks if offset is between -14:00 and +14:00.
const regex = /^([+-](0[0-9]|1[0-4]):[0-5][0-9])$/; //checks if offset is between -14:00 and +14:00.
//-12:00 is the lowest valid UTC-offset, but we allow down to -14 for efficiency
if (regex.test(offsetString)) {
const hhmm = offsetString.split(":");
@ -389,6 +389,19 @@ export class Utils {
const sign = (parts[3] === "N" || parts[3] === "E") ? 1 : -1;
return sign * (degrees + (minutes / 60.0))
}
public static sortableFilename(filename: string): string {
const lastDot = filename.lastIndexOf(".");
// Avoid 0 as well as -1 to prevent empty names for extensionless dot-files
if (lastDot > 0) {
return filename.substring(0, lastDot);
}
// Fallback to the full name
return filename;
}
}
export class LRU<V> {

View File

@ -132,8 +132,20 @@ export class GallerySortingService {
}
switch (sorting.method) {
case SortByTypes.Name:
media.sort((a: PhotoDTO, b: PhotoDTO) =>
this.collator.compare(a.name, b.name)
media.sort((a: PhotoDTO, b: PhotoDTO) => {
const aSortable = Utils.sortableFilename(a.name)
const bSortable = Utils.sortableFilename(b.name)
if (aSortable === bSortable) {
// If the trimmed filenames match, use the full name as tie breaker
// This preserves a consistent final position for files named e.g.,
// 10.jpg and 10.png, even if their starting position in the list
// changes based on any previous sorting that's happened under different heuristics
return this.collator.compare(a.name, b.name)
}
return this.collator.compare(aSortable, bSortable)
}
);
break;
case SortByTypes.Date:

View File

@ -58,4 +58,22 @@ describe('Utils', () => {
expect(Utils.equalsFilter({a: 0}, {b: 0})).to.be.equal(false);
expect(Utils.equalsFilter({a: 0}, {a: 0})).to.be.equal(true);
});
describe('sortableFilename', () => {
it('should trim extensions', () => {
expect(Utils.sortableFilename("10.jpg")).to.be.equal("10")
})
it('should not trim dotfiles to empty strings', () => {
expect(Utils.sortableFilename(".file")).to.be.equal(".file")
})
it('should trim dotfiles with extensions', () => {
expect(Utils.sortableFilename(".favourite.jpg")).to.be.equal(".favourite")
})
it('should not trim without dots', () => {
expect(Utils.sortableFilename("hello_world")).to.be.equal("hello_world")
})
})
});