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

Add support for video uploads. #268

Merged
merged 7 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
36 changes: 21 additions & 15 deletions example/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,50 @@ publisher:
email: [email protected]
media:
- purpose: icon
uri: ./media/publisher_icon.jpeg
uri: ./media/publisher_icon.png
app:
name: Cute Kittens
address: ''
android_package: com.solanamobile.cutekittens
urls:
license_url: https://cdn.org/license.html
copyright_url: https://cdn.org/copyright.html
privacy_policy_url: https://cdn.org/privacy.html
license_url: https://solanamobile.com/dapp-store-tos
copyright_url: https://solanamobile.com/dapp-store-tos
privacy_policy_url: https://solanamobile.com/privacy-policy
website: https://solanamobile.com
media:
- purpose: icon
uri: ./media/app_icon.jpeg
uri: ./media/app_icon.png
release:
address: ''
media:
- purpose: icon
uri: ./media/release_icon.png
- purpose: screenshot
uri: ./media/app_screenshot.png
uri: ./media/screenshot_1.png
- purpose: video
uri: ./media/demo.mp4
- purpose: screenshot
uri: ./media/app_screenshot1.png
uri: ./media/screenshot_2.png
- purpose: screenshot
uri: ./media/app_screenshot2.png
uri: ./media/screenshot_3.png
- purpose: screenshot
uri: ./media/app_screenshot3.png
- purpose: screenshot
uri: ./media/app_screenshot4.png
uri: ./media/screenshot_4.png
files:
- purpose: install
uri: ./files/app-debug.apk
uri: ./files/app-release.apk
catalog:
en-US:
name: This is a single release
short_description: A short description
name: Cute Kitten
short_description: Stories about cat
long_description: Some wonderful release notes, in long-form
new_in_version: Something new in this version
saga_features: Some information about saga specific features
fr-Fr:
name: App Name (in French)
short_description: App description (in French)
long_description: Some wonderful release notes, in long-form (in French)
new_in_version: Something new in this version (in French)
saga_features: Some information about saga specific features (in French)
solana_mobile_dapp_publisher_portal:
google_store_package: com.company.dapp.otherpkg
google_store_package: com.solanamobile.cutekitten.gps
testing_instructions: Here are some steps informing Solana Mobile of how to test this dapp. You can specify multiple lines of instructions. For example, if a login is needed, you would add those details here.
Binary file removed example/files/app-debug.apk
Binary file not shown.
Binary file added example/files/app-release.apk
Binary file not shown.
Binary file removed example/media/app_icon.jpeg
Binary file not shown.
Binary file added example/media/app_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed example/media/app_screenshot1.png
Binary file not shown.
Binary file removed example/media/app_screenshot2.png
Binary file not shown.
Binary file removed example/media/app_screenshot3.png
Binary file not shown.
Binary file removed example/media/app_screenshot4.png
Binary file not shown.
Binary file added example/media/demo.mp4
Binary file not shown.
Binary file removed example/media/publisher_icon.jpeg
Binary file not shown.
Binary file added example/media/publisher_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/media/release_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/media/screenshot_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/media/screenshot_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/media/screenshot_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/media/screenshot_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
},
"devDependencies": {
"@metaplex-foundation/js": "0.20.0",
"@jest/globals": "^29.5.0",
"@jest/types": "^29.5.0",
"@metaplex-foundation/js": "0.20.0",
"@swc/jest": "^0.2.26",
"@types/commander": "^2.12.2",
"@types/debug": "^4.1.7",
Expand Down Expand Up @@ -64,6 +64,7 @@
"dotenv": "^16.0.3",
"esm": "^3.2.25",
"generate-schema": "^2.6.0",
"get-video-dimensions": "^1.0.0",
"image-size": "^1.0.2",
"js-yaml": "^4.1.0",
"semver": "^7.3.8",
Expand Down
3 changes: 0 additions & 3 deletions packages/cli/src/commands/ValidateCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export const validateCommand = async ({

try {
validatePublisher(publisherJson);
console.info(`Publisher JSON valid!`);
} catch (e) {
const errorMsg = (e as Error | null)?.message ?? "";
showMessage(
Expand All @@ -55,7 +54,6 @@ export const validateCommand = async ({

try {
validateApp(appJson);
console.info(`App JSON valid!`);
} catch (e) {
const errorMsg = (e as Error | null)?.message ?? "";
showMessage(
Expand Down Expand Up @@ -86,7 +84,6 @@ export const validateCommand = async ({

try {
validateRelease(JSON.parse(objStringified));
console.info(`Release JSON valid!`);
} catch (e) {
const errorMsg = (e as Error | null)?.message ?? "";
showMessage(
Expand Down
61 changes: 54 additions & 7 deletions packages/cli/src/config/PublishDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { Constants, showMessage } from "../CliUtils.js";
import util from "util";
import { imageSize } from "image-size";
import { exec } from "child_process";
import getVideoDimensions from "get-video-dimensions";

const runImgSize = util.promisify(imageSize);
const runExec = util.promisify(exec);
Expand Down Expand Up @@ -125,19 +126,45 @@ export const loadPublishDetailsWithChecks = async (
}

config.release.media.forEach((item: PublishDetails["release"]["media"][0]) => {
const imagePath = path.join(process.cwd(), item.uri);
if (!fs.existsSync(imagePath) || !checkImageExtension(imagePath)) {
throw new Error(`Invalid media path or file type: ${item.uri}. Please ensure the file is a jpeg, png, or webp file.`);
const mediaPath = path.join(process.cwd(), item.uri);
if (!fs.existsSync(mediaPath)) {
throw new Error(`File doesnt exist: ${item.uri}.`)
}

if (item.purpose == "screenshot" && !checkImageExtension(mediaPath)) {
throw new Error(`Please ensure the file ${item.uri} is a jpeg, png, or webp file.`)
}

if (item.purpose == "video" && !checkVideoExtension(mediaPath)) {
throw new Error(`Please ensure the file ${item.uri} is a mp4.`)
}
}
);

const previewMediaFiles = config.release.media?.filter(
(asset: any) => asset.purpose === "screenshot" || asset.purpose === "video"
const screenshots = config.release.media?.filter(
(asset: any) => asset.purpose === "screenshot"
)

for (const item of screenshots) {
const mediaPath = path.join(process.cwd(), item.uri);
if (await checkScreenshotSize(mediaPath)) {
throw new Error(`Screenshot ${mediaPath} must be at least 1080px in width and height.`);
}
}

const videos = config.release.media?.filter(
(asset: any) => asset.purpose === "video"
)

if (previewMediaFiles.length < 4) {
throw new Error(`At least 4 screenshots or videos are required for publishing a new release. Found only ${previewMediaFiles.length}`)
for (const video of videos) {
const mediaPath = path.join(process.cwd(), video.uri);
if (await checkVideoSize(mediaPath)) {
throw new Error(`Video ${mediaPath} must be at least 1080px in width and height.`);
ankur2136 marked this conversation as resolved.
Show resolved Hide resolved
}
}

if (screenshots.length + videos.length < 4) {
throw new Error(`At least 4 screenshots or videos are required for publishing a new release. Found only ${screenshots.length + videos.length}`)
}

validateLocalizableResources(config);
Expand Down Expand Up @@ -174,6 +201,13 @@ const checkImageExtension = (uri: string): boolean => {
);
};

const checkVideoExtension = (uri: string): boolean => {
const fileExt = path.extname(uri).toLowerCase();
return (
fileExt == ".mp4"
);
};

/**
* We need to pre-check some things in the localized resources before we move forward
*/
Expand Down Expand Up @@ -206,6 +240,19 @@ const checkIconDimensions = async (iconPath: string): Promise<boolean> => {
return size?.width != size?.height || (size?.width ?? 0) != 512;
};

const checkScreenshotSize = async (imagePath: string): Promise<boolean> => {
const size = await runImgSize(imagePath);

return (size?.width ?? 0) < 1080 || (size?.height ?? 0) < 1080;
}

const checkVideoSize = async (imagePath: string): Promise<boolean> => {
const size = await getVideoDimensions(imagePath);

return (size?.width ?? 0) < 1080 || (size?.height ?? 0) < 1080;
}


const getAndroidDetails = async (
aaptDir: string,
apkPath: string
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@types/debug": "^4.1.7",
"@types/mime": "^3.0.1",
"@types/node-fetch": "^2.6.2",
"get-video-dimensions": "^1.0.0",
"json-schema-to-typescript": "^11.0.2",
"shx": "^0.3.4"
},
Expand Down
24 changes: 18 additions & 6 deletions packages/core/src/create/ReleaseCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Constants, mintNft } from "../CoreUtils.js";
import * as util from "util";
import { metaplexFileReplacer, validateRelease } from "../validate/CoreValidation.js";
import { imageSize } from "image-size";
import getVideoDimensions from "get-video-dimensions";

import type { Keypair, PublicKey } from "@solana/web3.js";
import type {
Expand Down Expand Up @@ -46,14 +47,25 @@ const getFileMetadata = async (item: Media | File) => {
};

const getMediaMetadata = async (item: Media) => {
const size = await runImgSize(item.uri ?? "");
const metadata = await getFileMetadata(item);

return {
...metadata,
width: size?.width ?? 0,
height: size?.height ?? 0,
};
if (item.purpose == "screenshot" || item.purpose == "icon") {
const size = await runImgSize(item.uri ?? "");

return {
...metadata,
width: size?.width ?? 0,
height: size?.height ?? 0,
};
} else {
const size = await getVideoDimensions(item.uri ?? "");

return {
...metadata,
width: size?.width ?? 0,
height: size?.height ?? 0,
};
}
};

export const createReleaseJson = async (
Expand Down
25 changes: 22 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading