Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Custom sort #258

Merged
merged 1 commit into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions web/src/themes/03_ONE_LINE/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ const ONE_LINE_OPTIONS: ThemeOption[] = [
{ id: 'FONT_SIZE', type: 'number', default: 70, description: 'px' },
{ id: 'FONT_FAMILY', type: 'select', options: ['Barlow', ...Object.values(Font)], default: 'Barlow', description: 'ex. din-alternate-bold, digital-7, Barlow, Arial, sans-serif' },
{ id: 'TOP_LABEL', type: 'string', default: '', description: 'ex. @username' },
{ id: 'DIVIDER', type: 'string', default: '|', description: 'ex. ∙' },
{ id: 'DIVIDER', type: 'string', default: '∙', description: 'ex. |' },
{ id: 'TEMPLATE', type: 'string', default: '{MAKER}{BODY}{LENS}{ISO}{MM}{F}{SEC}' },
];

const ONE_LINE_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store: Store) => {
Expand All @@ -37,6 +38,7 @@ const ONE_LINE_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store:
const FONT_FAMILY = (input.get('FONT_FAMILY') as string).trim();
const TOP_LABEL = (input.get('TOP_LABEL') as string).trim();
const DIVIDER = (input.get('DIVIDER') as string).trim();
const TEMPLATE = (input.get('TEMPLATE') as string).trim();

const canvas = sandbox(photo, {
targetRatio: store.ratio,
Expand All @@ -54,14 +56,21 @@ const ONE_LINE_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store:

context.textAlign = TEXT_ALIGN as CanvasTextAlign;

context.fillText(
[photo.make, photo.model, photo.lensModel, ...(store.disableExposureMeter ? [] : [`${photo.iso}`, `${photo.focalLength}`, `${photo.fNumber}`, `${photo.exposureTime}`])]
.filter(Boolean)
.map((value) => value!.trim())
.join(` ${DIVIDER} `),
TEXT_ALIGN === 'left' ? PADDING_LEFT : TEXT_ALIGN === 'center' ? canvas.width / 2 : canvas.width - PADDING_RIGHT,
canvas.height - PADDING_BOTTOM / 2
);
const text = TEMPLATE.split('}')
.filter(Boolean)
.map((part) => `${part}}`)
.join(' ' + DIVIDER + ' ')
.replace(/{MAKER}/g, photo.make)
.replace(/{BODY}/g, photo.model || '')
.replace(/{LENS}/g, photo.lensModel || '')
.replace(/{ISO}/g, store.disableExposureMeter ? '' : photo.iso || '')
.replace(/{MM}/g, store.disableExposureMeter ? '' : photo.focalLength || '')
.replace(/{F}/g, store.disableExposureMeter ? '' : photo.fNumber || '')
.replace(/{SEC}/g, store.disableExposureMeter ? '' : photo.exposureTime || '')
.replace(/{TAKEN_AT}/g, photo.takenAt || '')
.replace(/}/g, '');

context.fillText(text, TEXT_ALIGN === 'left' ? PADDING_LEFT : TEXT_ALIGN === 'center' ? canvas.width / 2 : canvas.width - PADDING_RIGHT, canvas.height - PADDING_BOTTOM / 2);

return canvas;
};
Expand Down
49 changes: 35 additions & 14 deletions web/src/themes/04_TWO_LINE/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ const TWO_LINE_OPTIONS: ThemeOption[] = [
{ id: 'FONT_SIZE', type: 'number', default: 70, description: 'px' },
{ id: 'FONT_FAMILY', type: 'select', options: ['Barlow', ...Object.values(Font)], default: 'Barlow', description: 'ex. din-alternate-bold, digital-7, Barlow, Arial, sans-serif' },
{ id: 'TOP_LABEL', type: 'string', default: '', description: 'ex. @username' },
{ id: 'DIVIDER', type: 'string', default: '|', description: 'ex. ∙' },
{ id: 'DIVIDER', type: 'string', default: '∙', description: 'ex. |' },
{ id: 'TEMPLATE1', type: 'string', default: '{MAKER}{BODY}{LENS}' },
{ id: 'TEMPLATE2', type: 'string', default: '{ISO}{MM}{F}{SEC}' },
];

const TWO_LINE_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store: Store) => {
Expand All @@ -37,6 +39,8 @@ const TWO_LINE_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store:
const FONT_FAMILY = (input.get('FONT_FAMILY') as string).trim();
const TOP_LABEL = (input.get('TOP_LABEL') as string).trim();
const DIVIDER = (input.get('DIVIDER') as string).trim();
const TEMPLATE1 = (input.get('TEMPLATE1') as string).trim();
const TEMPLATE2 = (input.get('TEMPLATE2') as string).trim();

const canvas = sandbox(photo, {
targetRatio: store.ratio,
Expand All @@ -52,22 +56,39 @@ const TWO_LINE_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store:
context.textAlign = 'center';
context.fillText(TOP_LABEL, canvas.width / 2, PADDING_TOP / 2);

const text1 = TEMPLATE1.split('}')
.filter(Boolean)
.map((part) => `${part}}`)
.join(' ' + DIVIDER + ' ')
.replace('{MAKER}', photo.make)
.replace('{BODY}', photo.model || '')
.replace('{LENS}', photo.lensModel || '')
.replace('{ISO}', store.disableExposureMeter ? '' : photo.iso || '')
.replace('{MM}', store.disableExposureMeter ? '' : photo.focalLength || '')
.replace('{F}', store.disableExposureMeter ? '' : photo.fNumber || '')
.replace('{SEC}', store.disableExposureMeter ? '' : photo.exposureTime || '')
.replace('{TAKEN_AT}', photo.takenAt || '')
.replace('}', '');

context.textAlign = TEXT_ALIGN as CanvasTextAlign;
context.fillText(
[photo.make, photo.model, photo.lensModel]
.filter(Boolean)
.map((value) => value!.trim())
.join(` ${DIVIDER} `),
TEXT_ALIGN === 'left' ? PADDING_LEFT : TEXT_ALIGN === 'center' ? canvas.width / 2 : canvas.width - PADDING_RIGHT,
canvas.height - PADDING_BOTTOM / 2 - FONT_SIZE / 1.5
);
context.fillText(text1, TEXT_ALIGN === 'left' ? PADDING_LEFT : TEXT_ALIGN === 'center' ? canvas.width / 2 : canvas.width - PADDING_RIGHT, canvas.height - PADDING_BOTTOM / 2 - FONT_SIZE / 1.5);

if (!store.disableExposureMeter) {
context.fillText(
[`${photo.iso}`, `${photo.focalLength}`, `${photo.fNumber}`, `${photo.exposureTime}`].filter(Boolean).join(` ${DIVIDER} `),
TEXT_ALIGN === 'left' ? PADDING_LEFT : TEXT_ALIGN === 'center' ? canvas.width / 2 : canvas.width - PADDING_RIGHT,
canvas.height - PADDING_BOTTOM / 2 + FONT_SIZE / 1.5
);
const text2 = TEMPLATE2.split('}')
.filter(Boolean)
.map((part) => `${part}}`)
.join(' ' + DIVIDER + ' ')
.replace(/{MAKER}/g, photo.make)
.replace(/{BODY}/g, photo.model || '')
.replace(/{LENS}/g, photo.lensModel || '')
.replace(/{ISO}/g, store.disableExposureMeter ? '' : photo.iso || '')
.replace(/{MM}/g, store.disableExposureMeter ? '' : photo.focalLength || '')
.replace(/{F}/g, store.disableExposureMeter ? '' : photo.fNumber || '')
.replace(/{SEC}/g, store.disableExposureMeter ? '' : photo.exposureTime || '')
.replace(/{TAKEN_AT}/g, photo.takenAt || '')
.replace(/}/g, '');

context.fillText(text2, TEXT_ALIGN === 'left' ? PADDING_LEFT : TEXT_ALIGN === 'center' ? canvas.width / 2 : canvas.width - PADDING_RIGHT, canvas.height - PADDING_BOTTOM / 2 + FONT_SIZE / 1.5);
}

return canvas;
Expand Down
85 changes: 68 additions & 17 deletions web/src/themes/07_STRAP/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ const STRAP_OPTIONS: ThemeOption[] = [
{ id: 'PADDING_BOTTOM', type: 'number', default: 0, description: 'px' },
{ id: 'PADDING_LEFT', type: 'number', default: 0, description: 'px' },
{ id: 'PADDING_RIGHT', type: 'number', default: 0, description: 'px' },
{ id: 'TEMPLATE1', type: 'string', default: '{ISO}{MM}{F}{SEC}' },
{ id: 'TEMPLATE2', type: 'string', default: '{MAKER}{BODY}' },
{ id: 'TEMPLATE3', type: 'string', default: '{TAKEN_AT}' },
{ id: 'TEMPLATE4', type: 'string', default: '{LENS}' },
];

const STRAP_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store: Store) => {
Expand All @@ -67,11 +71,71 @@ const STRAP_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store: Sto
const PADDING_BOTTOM = (input.get('PADDING_BOTTOM') as number) + 300;
const PADDING_LEFT = input.get('PADDING_LEFT') as number;
const PADDING_RIGHT = input.get('PADDING_RIGHT') as number;
const TEMPLATE1 = (input.get('TEMPLATE1') as string).trim();
const TEMPLATE2 = (input.get('TEMPLATE2') as string).trim();
const TEMPLATE3 = (input.get('TEMPLATE3') as string).trim();
const TEMPLATE4 = (input.get('TEMPLATE4') as string).trim();
const FONT_SIZE = 70;
const BACKGROUND_COLOR = DARK_MODE ? '#000000' : '#ffffff';
const PRIMARY_TEXT_COLOR = DARK_MODE ? '#ffffff' : '#000000';
const SECONDARY_TEXT_COLOR = DARK_MODE ? '#888888' : '#333333';

const text1 = TEMPLATE1.split('}')
.filter(Boolean)
.map((part) => `${part}}`)
.join(' ')
.replace(/{MAKER}/g, photo.make)
.replace(/{BODY}/g, photo.model || '')
.replace(/{LENS}/g, photo.lensModel || '')
.replace(/{ISO}/g, store.disableExposureMeter ? '' : photo.iso || '')
.replace(/{MM}/g, store.disableExposureMeter ? '' : photo.focalLength || '')
.replace(/{F}/g, store.disableExposureMeter ? '' : photo.fNumber || '')
.replace(/{SEC}/g, store.disableExposureMeter ? '' : photo.exposureTime || '')
.replace(/{TAKEN_AT}/g, photo.takenAt || '')
.replace(/}/g, '');

const text2 = TEMPLATE2.split('}')
.filter(Boolean)
.map((part) => `${part}}`)
.join(' ')
.replace(/{MAKER}/g, photo.make)
.replace(/{BODY}/g, photo.model || '')
.replace(/{LENS}/g, photo.lensModel || '')
.replace(/{ISO}/g, store.disableExposureMeter ? '' : photo.iso || '')
.replace(/{MM}/g, store.disableExposureMeter ? '' : photo.focalLength || '')
.replace(/{F}/g, store.disableExposureMeter ? '' : photo.fNumber || '')
.replace(/{SEC}/g, store.disableExposureMeter ? '' : photo.exposureTime || '')
.replace(/{TAKEN_AT}/g, photo.takenAt || '')
.replace(/}/g, '');

const text3 = TEMPLATE3.split('}')
.filter(Boolean)
.map((part) => `${part}}`)
.join(' ')
.replace(/{MAKER}/g, photo.make)
.replace(/{BODY}/g, photo.model || '')
.replace(/{LENS}/g, photo.lensModel || '')
.replace(/{ISO}/g, store.disableExposureMeter ? '' : photo.iso || '')
.replace(/{MM}/g, store.disableExposureMeter ? '' : photo.focalLength || '')
.replace(/{F}/g, store.disableExposureMeter ? '' : photo.fNumber || '')
.replace(/{SEC}/g, store.disableExposureMeter ? '' : photo.exposureTime || '')
.replace(/{TAKEN_AT}/g, photo.takenAt || '')
.replace(/}/g, '');

const text4 = TEMPLATE4.split('}')
.filter(Boolean)
.map((part) => `${part}}`)
.join(' ')
.replace(/{MAKER}/g, photo.make)
.replace(/{BODY}/g, photo.model || '')
.replace(/{LENS}/g, photo.lensModel || '')
.replace(/{ISO}/g, store.disableExposureMeter ? '' : photo.iso || '')
.replace(/{MM}/g, store.disableExposureMeter ? '' : photo.focalLength || '')
.replace(/{F}/g, store.disableExposureMeter ? '' : photo.fNumber || '')
.replace(/{SEC}/g, store.disableExposureMeter ? '' : photo.exposureTime || '')
.replace(/{TAKEN_AT}/g, photo.takenAt || '')
.replace(/}/g, '');

const canvas = sandbox(photo, {
targetRatio: store.ratio,
notCroppedMode: store.notCroppedMode,
Expand All @@ -89,14 +153,7 @@ const STRAP_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store: Sto
context.fillStyle = PRIMARY_TEXT_COLOR;

if (!store.disableExposureMeter) {
context.fillText(
[`${photo.iso}`, `${photo.focalLength}`, `${photo.fNumber}`, `${photo.exposureTime}`]
.filter(Boolean)
.map((value) => value.trim())
.join(' '),
FONT_SIZE,
canvas.height - PADDING_BOTTOM / 2 - FONT_SIZE / 2
);
context.fillText(text1, FONT_SIZE, canvas.height - PADDING_BOTTOM / 2 - FONT_SIZE / 2);
}

// Shot by
Expand All @@ -107,7 +164,7 @@ const STRAP_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store: Sto
} else {
context.font = `normal ${SECONDARY_TEXT_FONT_WEIGHT} ${FONT_SIZE}px Barlow`;
context.fillStyle = SECONDARY_TEXT_COLOR;
context.fillText(photo.takenAt, FONT_SIZE, canvas.height - PADDING_BOTTOM / 2 + FONT_SIZE / 2);
context.fillText(text3, FONT_SIZE, canvas.height - PADDING_BOTTOM / 2 + FONT_SIZE / 2);
}

// RIGHT SECOND
Expand All @@ -116,20 +173,14 @@ const STRAP_FUNC: ThemeFunc = (photo: Photo, input: ThemeOptionInput, store: Sto
// Maker, Model
context.fillStyle = PRIMARY_TEXT_COLOR;
context.font = `normal 500 ${FONT_SIZE}px Barlow`;
const makerModelText = [photo.make, photo.model]
.filter(Boolean)
.map((value) => value!.trim())
.join(' ');
const makerModelText = text2;
const topWidth = context.measureText(makerModelText).width;
context.fillText(makerModelText, canvas.width - FONT_SIZE, canvas.height - PADDING_BOTTOM / 2 - FONT_SIZE / 2);

// Lens Model
context.fillStyle = SECONDARY_TEXT_COLOR;
context.font = `normal ${SECONDARY_TEXT_FONT_WEIGHT} ${FONT_SIZE}px Barlow`;
const lensModelText = [photo.lensModel]
.filter(Boolean)
.map((value) => value!.trim())
.join(' ');
const lensModelText = text4;
const bottomWidth = context.measureText(lensModelText).width;
context.fillText(lensModelText, canvas.width - FONT_SIZE, canvas.height - PADDING_BOTTOM / 2 + FONT_SIZE / 2);

Expand Down