Create a package to share code between photos and cast

This commit is contained in:
Manav Rathi 2024-04-17 09:41:10 +05:30
parent 486044ad51
commit 4b9446a9b0
No known key found for this signature in database
7 changed files with 88 additions and 3 deletions

View file

@ -110,7 +110,7 @@ with Next.js.
For more details, see [translations.md](translations.md).
## Meta Frameworks
## Meta frameworks
### Next.js
@ -131,7 +131,12 @@ It is more lower level than Next, but the bells and whistles it doesn't have are
the bells and whistles (and the accompanying complexity) that we don't need in
some cases.
## Photos
## Media
- "jszip" is used for reading zip files in JavaScript. Live photos are zip files
under the hood.
## Photos app specific
### Misc

View file

@ -0,0 +1,3 @@
module.exports = {
extends: ["@/build-config/eslintrc-next"],
};

View file

@ -0,0 +1,11 @@
## @/media
A package for sharing code between our apps that show media (photos, videos).
Specifically, this is the intersection of code required by both the photos and
cast apps.
### Packaging
This (internal) package exports a React TypeScript library. We rely on the
importing project to transpile and bundle it.

View file

@ -0,0 +1,52 @@
import JSZip from "jszip";
class LivePhoto {
image: Uint8Array;
video: Uint8Array;
imageNameTitle: string;
videoNameTitle: string;
}
export function getFileNameWithoutExtension(filename: string) {
const lastDotPosition = filename.lastIndexOf(".");
if (lastDotPosition === -1) return filename;
else return filename.slice(0, lastDotPosition);
}
export function getFileExtensionWithDot(filename: string) {
const lastDotPosition = filename.lastIndexOf(".");
if (lastDotPosition === -1) return "";
else return filename.slice(lastDotPosition);
}
export const decodeLivePhoto = async (fileName: string, zipBlob: Blob) => {
const originalName = getFileNameWithoutExtension(fileName);
const zip = await JSZip.loadAsync(zipBlob, { createFolders: true });
const livePhoto = new LivePhoto();
for (const zipFilename in zip.files) {
if (zipFilename.startsWith("image")) {
livePhoto.imageNameTitle =
originalName + getFileExtensionWithDot(zipFilename);
livePhoto.image = await zip.files[zipFilename].async("uint8array");
} else if (zipFilename.startsWith("video")) {
livePhoto.videoNameTitle =
originalName + getFileExtensionWithDot(zipFilename);
livePhoto.video = await zip.files[zipFilename].async("uint8array");
}
}
return livePhoto;
};
export const encodeLivePhoto = async (livePhoto: LivePhoto) => {
const zip = new JSZip();
zip.file(
"image" + getFileExtensionWithDot(livePhoto.imageNameTitle),
livePhoto.image,
);
zip.file(
"video" + getFileExtensionWithDot(livePhoto.videoNameTitle),
livePhoto.video,
);
return await zip.generateAsync({ type: "uint8array" });
};

View file

@ -0,0 +1,9 @@
{
"name": "@/media",
"version": "0.0.0",
"private": true,
"dependencies": {
"@/next": "*",
"jszip": "^3.10"
}
}

View file

@ -0,0 +1,5 @@
{
"extends": "@/build-config/tsconfig-typecheck.json",
/* Typecheck all files with the given extensions (here or in subfolders) */
"include": ["**/*.ts", "**/*.tsx"]
}

View file

@ -3252,7 +3252,7 @@ jssha@~3.3.1:
object.assign "^4.1.4"
object.values "^1.1.6"
jszip@3.10.1:
jszip@3.10.1, jszip@^3.10:
version "3.10.1"
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2"
integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==