-
Notifications
You must be signed in to change notification settings - Fork 12
fix: photos are optional #390
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
Merged
+1,656
−679
Merged
Changes from 3 commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
f260928
fix: photos are optional
raven-wing f72d4e8
added missing file
raven-wing eb31ece
fix: error is actually visible now
raven-wing 2b0b6f9
docs added
raven-wing 7d12b3a
fix lint
raven-wing 6cd52a6
added missing files
raven-wing c538556
fix docs
raven-wing 4553d7e
fixes
raven-wing 042458a
fix scroll
raven-wing bae24fa
load spinner
raven-wing 9a37fcc
fix docs
raven-wing a275e24
fix docs
raven-wing 02ddc3e
fix
raven-wing f9af39a
little cleanup
raven-wing c8fc966
fixes after update
raven-wing 7a0a319
fixed comments
raven-wing 8a880e4
little refactor
raven-wing 8d785aa
removed compressing from our site
raven-wing f39c8da
fixes
raven-wing 3df1861
added dependency
raven-wing 5e9009c
splitted suggest new point behaviour
raven-wing 4385180
little refactor
raven-wing 4c6d28b
dead code
raven-wing afa8f07
code cleanup
raven-wing 434fb69
some cleanup
raven-wing 5fc4ecd
lint fixes
raven-wing 630b97d
fix after review
raven-wing c9347de
removed dead code
raven-wing ba408bb
refactor
raven-wing ec63578
fix licenses
raven-wing f3ff1cc
refactor
raven-wing 2f0c4bc
remove some extra check
raven-wing bc99d6c
simplify
raven-wing 9993bd2
fix after review
raven-wing b288dc9
fixes after review
raven-wing e94bb19
fix after review
raven-wing 31c7915
little refactor
raven-wing fb361bc
lint fix
raven-wing f58f4c4
refactor test
raven-wing 2cf6fa0
some renames
raven-wing 22b9dad
added docs with feature flags
raven-wing 32d1b49
docs fix
raven-wing File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| // Only the backend's allowed extensions are worth targeting (jpeg/jpg), so we | ||
| // always re-encode to JPEG regardless of the source format. | ||
| const MIN_QUALITY = 0.4; | ||
| const QUALITY_STEP = 0.1; | ||
|
|
||
| const loadImage = file => | ||
| new Promise((resolve, reject) => { | ||
| const objectUrl = URL.createObjectURL(file); | ||
| const img = new Image(); | ||
| img.onload = () => { | ||
| URL.revokeObjectURL(objectUrl); | ||
| resolve(img); | ||
| }; | ||
| img.onerror = () => { | ||
| URL.revokeObjectURL(objectUrl); | ||
| reject(new Error('Failed to load image for compression')); | ||
| }; | ||
| img.src = objectUrl; | ||
| }); | ||
|
|
||
| const canvasToBlob = (canvas, quality) => | ||
| new Promise((resolve, reject) => { | ||
| canvas.toBlob( | ||
| blob => (blob ? resolve(blob) : reject(new Error('Image encoding failed'))), | ||
| 'image/jpeg', | ||
| quality, | ||
| ); | ||
| }); | ||
|
|
||
| /** | ||
| * Re-encodes an image file as JPEG, scaling it down to fit within maxDimension | ||
| * and lowering quality as needed to land under maxSizeBytes. | ||
| * | ||
| * @param {File} file - Source image file. | ||
| * @param {{maxSizeBytes?: number, maxDimension?: number}} options | ||
| * @returns {Promise<File>} Compressed JPEG file (may still exceed maxSizeBytes | ||
| * if the image can't be reduced further without going below MIN_QUALITY). | ||
| */ | ||
| export const compressImageToJpeg = async (file, { maxSizeBytes, maxDimension = 1920 } = {}) => { | ||
| const img = await loadImage(file); | ||
|
|
||
| const scale = Math.min(1, maxDimension / Math.max(img.width, img.height)); | ||
| const width = Math.round(img.width * scale); | ||
| const height = Math.round(img.height * scale); | ||
|
|
||
| const canvas = document.createElement('canvas'); | ||
| canvas.width = width; | ||
| canvas.height = height; | ||
| const context = canvas.getContext('2d'); | ||
| // JPEG has no alpha channel; without this, transparent PNG areas default to | ||
| // black (canvas pixels start as rgba(0,0,0,0), and the alpha just gets dropped). | ||
| context.fillStyle = '#fff'; | ||
| context.fillRect(0, 0, width, height); | ||
| context.drawImage(img, 0, 0, width, height); | ||
|
|
||
| let quality = 0.9; | ||
| let blob = await canvasToBlob(canvas, quality); | ||
| while (blob.size > maxSizeBytes && quality > MIN_QUALITY) { | ||
| quality -= QUALITY_STEP; | ||
| blob = await canvasToBlob(canvas, quality); | ||
| } | ||
|
|
||
| const baseName = file.name.replace(/\.[^./\\]+$/, '') || 'photo'; | ||
| return new File([blob], `${baseName}.jpg`, { type: 'image/jpeg' }); | ||
| }; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.