جاوااسکریپت - چگونه میتوان بدون اجرای expo prebuild برای ایجاد پوشه اندروید، تصاویر را به منابع drawable اندروید در Expo اضافه کرد


من در حال تلاش برای استفاده از react-native-quick-actions با expo هستم و از پلاگین تنظیمات آن طبق پیشنهاد در انجمن expo استفاده میکنم. میانبرها کار میکنند، اما نمیتوانم یک تصویر سفارشی برای میانبر در اندروید تنظیم کنم. طبق مستندات، باید تصاویر را در پوشه drawable در اندروید اضافه کنم. میدانم که اجرای expo prebuild یک پوشه اندروید ایجاد میکند، اما سعی دارم از آن دوری کنم، زیرا فقط چند تصویر است.

من تلاش کردم از assets و require استفاده کنم، اما این کار نمیکند.

من اطلاع دارم که پلاگینهای پیکربندی ممکن است بتوانند فایلها را در طی expo prebuild جابجا کنند (وقتی روی EAS ساخته میشود)، اما هیچ موردی پیدا نکردهام.

پاسخ شماره ۱

من یک روش با استفاده از پلاگینهای کانفیگ پیدا کردم. این روش زمانی اجرا میشود که ما expo prebuild را اجرا کنیم، چه روی دستگاه محلی و چه در EAS، و محتویات پوشههای مشخص شده را در پوشه drawable در اندروید کپی میکند.

من فکر میکنم میتوان آن را برای iOS تغییر داد.

یک فایل با نام withDrawableAssets.ts ایجاد کنید و کد زیر را در آن جایگذاری کنید. قبل از استفاده، نیاز دارید آن را به جاوااسکریپت کامپایل کنید.

import type { ConfigPlugin } from "@expo/config-plugins";

import { existsSync, mkdirSync, lstatSync, readdirSync, copyFileSync } from "fs";
import { join, basename } from "path";

import { withDangerousMod } from "@expo/config-plugins";

const androidFolderPath = ["app", "src", "main", "res", "drawable"];

const withDrawableAssets: ConfigPlugin<string | string[]> = (expoConfig, files) =>
  withDangerousMod(expoConfig, [
    "android",
    (modConfig) => {
      if (modConfig.modRequest.platform === "android") {
        const androidDwarablePath = join(modConfig.modRequest.platformProjectRoot, ...androidFolderPath);
        if (!Array.isArray(files)) {
          files = [files];
        }

        files.forEach((file) => {
          const isFile = lstatSync(file).isFile();
          if (isFile) {
            copyFileSync(file, join(androidDwarablePath, basename(file)));
          } else {
            copyFolderRecursiveSync(file, androidDwarablePath);
          }
        });
      }
      return modConfig;
    },
  ]);

async function copyFolderRecursiveSync(source: string, target: string) {
  if (!existsSync(target)) mkdirSync(target);

  const files = readdirSync(source);

  files.forEach(async (file) => {
    const sourcePath = join(source, file);
    const targetPath = join(target, file);

    if (lstatSync(sourcePath).isDirectory()) {
      copyFolderRecursiveSync(sourcePath, targetPath);
    } else {
      copyFileSync(sourcePath, targetPath);
    }
  });
}

export default withDrawableAssets;

استفاده در app.json

{
  "expo": {
      ... // rest of app.json
      "plugins": [["./withDrawableAssets.js","./assets/shortcuts"] ,"@config-plugins/react-native-quick-actions"]
//./assets/shortcuts is the name of the name of folder I wanted to copy to the drawable folder 
  }
}

پاسخ شماره ۲

مثل جادو کار میکند!! مرسی .. این هم کد جاوااسکریپت

    const fs = require("fs");
const path = require("path");
const { withDangerousMod } = require("@expo/config-plugins");

const androidFolderPath = ["app", "src", "main", "res", "drawable"];

const withDrawableAssets = function (expoConfig, files) {
  return withDangerousMod(expoConfig, [
    "android",
    function (modConfig) {
      if (modConfig.modRequest.platform === "android") {
        const androidDwarablePath = path.join(
          modConfig.modRequest.platformProjectRoot,
          ...androidFolderPath
        );

        if (!Array.isArray(files)) {
          files = [files];
        }

        files.forEach(function (file) {
          const isFile = fs.lstatSync(file).isFile();
          if (isFile) {
            fs.copyFileSync(file, path.join(androidDwarablePath, path.basename(file)));
          } else {
            copyFolderRecursiveSync(file, androidDwarablePath);
          }
        });
      }
      return modConfig;
    },
  ]);
};

function copyFolderRecursiveSync(source, target) {
  if (!fs.existsSync(target)) fs.mkdirSync(target);

  const files = fs.readdirSync(source);

  files.forEach(function (file) {
    const sourcePath = path.join(source, file);
    const targetPath = path.join(target, file);

    if (fs.lstatSync(sourcePath).isDirectory()) {
      copyFolderRecursiveSync(sourcePath, targetPath);
    } else {
      fs.copyFileSync(sourcePath, targetPath);
    }
  });
}

module.exports = withDrawableAssets;