diff --git a/AppEntry.ts b/AppEntry.ts index ef532da..9970d71 100644 --- a/AppEntry.ts +++ b/AppEntry.ts @@ -1,4 +1,4 @@ -import registerRootComponent from 'expo/build/launch/registerRootComponent'; +import { registerRootComponent } from 'expo'; import App from "App"; registerRootComponent(App); \ No newline at end of file diff --git a/android/.gitignore b/android/.gitignore index 877b87e..8a6be07 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -10,6 +10,7 @@ build/ local.properties *.iml *.hprof +.cxx/ # Bundle artifacts *.jsbundle diff --git a/android/app/build.gradle b/android/app/build.gradle index 0986ee6..88dfc29 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,4 +1,5 @@ apply plugin: "com.android.application" +apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath() @@ -11,20 +12,21 @@ react { entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim()) reactNativeDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile() hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc" - codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile() + codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile() + enableBundleCompression = (findProperty('android.enableBundleCompression') ?: false).toBoolean() // Use Expo CLI to bundle the app, this ensures the Metro config // works correctly with Expo projects. - cliFile = new File(["node", "--print", "require.resolve('@expo/cli')"].execute(null, rootDir).text.trim()) + cliFile = new File(["node", "--print", "require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })"].execute(null, rootDir).text.trim()) bundleCommand = "export:embed" /* Folders */ - // The root of your project, i.e. where "package.json" lives. Default is '..' - // root = file("../") - // The folder where the react-native NPM package is. Default is ../node_modules/react-native - // reactNativeDir = file("../node_modules/react-native") - // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen - // codegenDir = file("../node_modules/@react-native/codegen") + // The root of your project, i.e. where "package.json" lives. Default is '../..' + // root = file("../../") + // The folder where the react-native NPM package is. Default is ../../node_modules/react-native + // reactNativeDir = file("../../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen + // codegenDir = file("../../node_modules/@react-native/codegen") /* Variants */ // The list of variants to that are debuggable. For those we're going to @@ -56,6 +58,9 @@ react { // // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" // hermesFlags = ["-O", "-output-source-map"] + + /* Autolinking */ + autolinkLibrariesWithApp() } /** @@ -74,12 +79,13 @@ def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInRelea * give correct results when using with locales other than en-US. Note that * this variant is about 6MiB larger per architecture than default. */ -def jscFlavor = 'org.webkit:android-jsc:+' +def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+' android { ndkVersion rootProject.ext.ndkVersion - compileSdkVersion rootProject.ext.compileSdkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + compileSdk rootProject.ext.compileSdkVersion namespace 'com.anonymous.Assemblr' defaultConfig { @@ -87,9 +93,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 - versionName "1.3.4" - - buildConfigField("boolean", "REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS", (findProperty("reactNative.unstable_useRuntimeSchedulerAlways") ?: true).toString()) + versionName "1.4.0" } signingConfigs { debug { @@ -110,8 +114,17 @@ android { shrinkResources (findProperty('android.enableShrinkResourcesInReleaseBuilds')?.toBoolean() ?: false) minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + crunchPngs (findProperty('android.enablePngCrunchInReleaseBuilds')?.toBoolean() ?: true) } } + packagingOptions { + jniLibs { + useLegacyPackaging (findProperty('expo.useLegacyPackaging')?.toBoolean() ?: false) + } + } + androidResources { + ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~' + } } // Apply static values from `gradle.properties` to the `android.packagingOptions` @@ -141,40 +154,24 @@ dependencies { def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true"; def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true"; def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true"; - def frescoVersion = rootProject.ext.frescoVersion - - // If your app supports Android versions before Ice Cream Sandwich (API level 14) - if (isGifEnabled || isWebpEnabled) { - implementation("com.facebook.fresco:fresco:${frescoVersion}") - implementation("com.facebook.fresco:imagepipeline-okhttp3:${frescoVersion}") - } - + implementation project(':react-native-tcp-socket') if (isGifEnabled) { // For animated gif support - implementation("com.facebook.fresco:animated-gif:${frescoVersion}") + implementation("com.facebook.fresco:animated-gif:${expoLibs.versions.fresco.get()}") } if (isWebpEnabled) { // For webp support - implementation("com.facebook.fresco:webpsupport:${frescoVersion}") + implementation("com.facebook.fresco:webpsupport:${expoLibs.versions.fresco.get()}") if (isWebpAnimatedEnabled) { // Animated webp support - implementation("com.facebook.fresco:animated-webp:${frescoVersion}") + implementation("com.facebook.fresco:animated-webp:${expoLibs.versions.fresco.get()}") } } - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") - debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { - exclude group:'com.squareup.okhttp3', module:'okhttp' - } - debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") - if (hermesEnabled.toBoolean()) { implementation("com.facebook.react:hermes-android") } else { implementation jscFlavor } } - -apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle"); -applyNativeModulesAppBuildGradle(project) diff --git a/android/app/src/debug/java/com/anonymous/Assemblr/ReactNativeFlipper.java b/android/app/src/debug/java/com/anonymous/Assemblr/ReactNativeFlipper.java deleted file mode 100644 index 7ef8f76..0000000 --- a/android/app/src/debug/java/com/anonymous/Assemblr/ReactNativeFlipper.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - */ -package com.anonymous.Assemblr; - -import android.content.Context; -import com.facebook.flipper.android.AndroidFlipperClient; -import com.facebook.flipper.android.utils.FlipperUtils; -import com.facebook.flipper.core.FlipperClient; -import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; -import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; -import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; -import com.facebook.flipper.plugins.inspector.DescriptorMapping; -import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; -import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; -import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; -import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; -import com.facebook.react.ReactInstanceEventListener; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.modules.network.NetworkingModule; -import okhttp3.OkHttpClient; - -/** - * Class responsible of loading Flipper inside your React Native application. This is the debug - * flavor of it. Here you can add your own plugins and customize the Flipper setup. - */ -public class ReactNativeFlipper { - public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { - if (FlipperUtils.shouldEnableFlipper(context)) { - final FlipperClient client = AndroidFlipperClient.getInstance(context); - - client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); - client.addPlugin(new DatabasesFlipperPlugin(context)); - client.addPlugin(new SharedPreferencesFlipperPlugin(context)); - client.addPlugin(CrashReporterPlugin.getInstance()); - - NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); - NetworkingModule.setCustomClientBuilder( - new NetworkingModule.CustomClientBuilder() { - @Override - public void apply(OkHttpClient.Builder builder) { - builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); - } - }); - client.addPlugin(networkFlipperPlugin); - client.start(); - - // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized - // Hence we run if after all native modules have been initialized - ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); - if (reactContext == null) { - reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceEventListener() { - @Override - public void onReactContextInitialized(ReactContext reactContext) { - reactInstanceManager.removeReactInstanceEventListener(this); - reactContext.runOnNativeModulesQueueThread( - new Runnable() { - @Override - public void run() { - client.addPlugin(new FrescoFlipperPlugin()); - } - }); - } - }); - } else { - client.addPlugin(new FrescoFlipperPlugin()); - } - } - } -} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a4eac01..403ab21 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -14,12 +14,11 @@ - + - - + @@ -28,10 +27,8 @@ - - \ No newline at end of file diff --git a/android/app/src/main/java/com/anonymous/Assemblr/MainActivity.java b/android/app/src/main/java/com/anonymous/Assemblr/MainActivity.java deleted file mode 100644 index 6e5cee7..0000000 --- a/android/app/src/main/java/com/anonymous/Assemblr/MainActivity.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.anonymous.Assemblr; -// @generated begin react-native-keyevent-import - expo prebuild (DO NOT MODIFY) sync-6d2345dd84c398e4e99d7d44eb792294628c7e34 -import android.view.KeyEvent; -import com.github.kevinejohn.keyevent.KeyEventModule; -// @generated end react-native-keyevent-import - -import android.os.Build; -import android.os.Bundle; - -import com.facebook.react.ReactActivity; -import com.facebook.react.ReactActivityDelegate; -import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; -import com.facebook.react.defaults.DefaultReactActivityDelegate; - -import expo.modules.ReactActivityDelegateWrapper; - -public class MainActivity extends ReactActivity { -// @generated begin react-native-keyevent-body - expo prebuild (DO NOT MODIFY) sync-4ba28f58cc0b4a775aa231e380b7f40e8f34382a -@Override -public boolean onKeyDown(int keyCode, KeyEvent event) { - - // // Uncomment this is key events should only trigger once when key is held down - // if (event.getRepeatCount() == 0) { - // KeyEventModule.getInstance().onKeyDownEvent(keyCode, event); - // } - - // // This will trigger the key repeat if the key is held down - // // Comment this out if uncommenting the above - KeyEventModule.getInstance().onKeyDownEvent(keyCode, event); - - // // Uncomment this if you want the default keyboard behavior - // return super.onKeyDown(keyCode, event); - - // // The default keyboard behaviour wll be overridden - // // This is similar to what e.preventDefault() does in a browser - // // comment this if uncommenting the above - super.onKeyDown(keyCode, event); - return true; -} - -@Override -public boolean onKeyUp(int keyCode, KeyEvent event) { - KeyEventModule.getInstance().onKeyUpEvent(keyCode, event); - - // // Uncomment this if you want the default keyboard behavior - // return super.onKeyUp(keyCode, event); - - // // The default keyboard behaviour wll be overridden - // // This is similar to what e.preventDefault() does in a browser - // // comment this if uncommenting the above - super.onKeyUp(keyCode, event); - return true; -} - -@Override -public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { - KeyEventModule.getInstance().onKeyMultipleEvent(keyCode, repeatCount, event); - return super.onKeyMultiple(keyCode, repeatCount, event); -} -// @generated end react-native-keyevent-body - @Override - protected void onCreate(Bundle savedInstanceState) { - // Set the theme to AppTheme BEFORE onCreate to support - // coloring the background, status bar, and navigation bar. - // This is required for expo-splash-screen. - setTheme(R.style.AppTheme); - super.onCreate(null); - } - - /** - * Returns the name of the main component registered from JavaScript. - * This is used to schedule rendering of the component. - */ - @Override - protected String getMainComponentName() { - return "main"; - } - - /** - * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link - * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React - * (aka React 18) with two boolean flags. - */ - @Override - protected ReactActivityDelegate createReactActivityDelegate() { - return new ReactActivityDelegateWrapper(this, BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, new DefaultReactActivityDelegate( - this, - getMainComponentName(), - // If you opted-in for the New Architecture, we enable the Fabric Renderer. - DefaultNewArchitectureEntryPoint.getFabricEnabled())); - } - - /** - * Align the back button behavior with Android S - * where moving root activities to background instead of finishing activities. - * @see onBackPressed - */ - @Override - public void invokeDefaultOnBackPressed() { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { - if (!moveTaskToBack(false)) { - // For non-root activities, use the default implementation to finish them. - super.invokeDefaultOnBackPressed(); - } - return; - } - - // Use the default back button implementation on Android S - // because it's doing more than {@link Activity#moveTaskToBack} in fact. - super.invokeDefaultOnBackPressed(); - } -} diff --git a/android/app/src/main/java/com/anonymous/Assemblr/MainActivity.kt b/android/app/src/main/java/com/anonymous/Assemblr/MainActivity.kt new file mode 100644 index 0000000..fefb5d8 --- /dev/null +++ b/android/app/src/main/java/com/anonymous/Assemblr/MainActivity.kt @@ -0,0 +1,65 @@ +package com.anonymous.Assemblr +import expo.modules.splashscreen.SplashScreenManager + +import android.os.Build +import android.os.Bundle + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +import expo.modules.ReactActivityDelegateWrapper + +class MainActivity : ReactActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + // Set the theme to AppTheme BEFORE onCreate to support + // coloring the background, status bar, and navigation bar. + // This is required for expo-splash-screen. + // setTheme(R.style.AppTheme); + // @generated begin expo-splashscreen - expo prebuild (DO NOT MODIFY) sync-f3ff59a738c56c9a6119210cb55f0b613eb8b6af + SplashScreenManager.registerOnActivity(this) + // @generated end expo-splashscreen + super.onCreate(null) + } + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "main" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate { + return ReactActivityDelegateWrapper( + this, + BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, + object : DefaultReactActivityDelegate( + this, + mainComponentName, + fabricEnabled + ){}) + } + + /** + * Align the back button behavior with Android S + * where moving root activities to background instead of finishing activities. + * @see onBackPressed + */ + override fun invokeDefaultOnBackPressed() { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + if (!moveTaskToBack(false)) { + // For non-root activities, use the default implementation to finish them. + super.invokeDefaultOnBackPressed() + } + return + } + + // Use the default back button implementation on Android S + // because it's doing more than [Activity.moveTaskToBack] in fact. + super.invokeDefaultOnBackPressed() + } +} diff --git a/android/app/src/main/java/com/anonymous/Assemblr/MainApplication.java b/android/app/src/main/java/com/anonymous/Assemblr/MainApplication.java deleted file mode 100644 index 35c6de4..0000000 --- a/android/app/src/main/java/com/anonymous/Assemblr/MainApplication.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.anonymous.Assemblr; - -import android.app.Application; -import android.content.res.Configuration; -import androidx.annotation.NonNull; - -import com.facebook.react.PackageList; -import com.facebook.react.ReactApplication; -import com.facebook.react.ReactNativeHost; -import com.facebook.react.ReactPackage; -import com.facebook.react.config.ReactFeatureFlags; -import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; -import com.facebook.react.defaults.DefaultReactNativeHost; -import com.facebook.soloader.SoLoader; - -import expo.modules.ApplicationLifecycleDispatcher; -import expo.modules.ReactNativeHostWrapper; - -import java.util.List; - -public class MainApplication extends Application implements ReactApplication { - - private final ReactNativeHost mReactNativeHost = - new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) { - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } - - @Override - protected List getPackages() { - @SuppressWarnings("UnnecessaryLocalVariable") - List packages = new PackageList(this).getPackages(); - // Packages that cannot be autolinked yet can be added manually here, for example: - // packages.add(new MyReactNativePackage()); - return packages; - } - - @Override - protected String getJSMainModuleName() { - return ".expo/.virtual-metro-entry"; - } - - @Override - protected boolean isNewArchEnabled() { - return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; - } - - @Override - protected Boolean isHermesEnabled() { - return BuildConfig.IS_HERMES_ENABLED; - } - }); - - @Override - public ReactNativeHost getReactNativeHost() { - return mReactNativeHost; - } - - @Override - public void onCreate() { - super.onCreate(); - SoLoader.init(this, /* native exopackage */ false); - if (!BuildConfig.REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS) { - ReactFeatureFlags.unstable_useRuntimeSchedulerAlways = false; - } - if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { - // If you opted-in for the New Architecture, we load the native entry point for this app. - DefaultNewArchitectureEntryPoint.load(); - } - ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - ApplicationLifecycleDispatcher.onApplicationCreate(this); - } - - @Override - public void onConfigurationChanged(@NonNull Configuration newConfig) { - super.onConfigurationChanged(newConfig); - ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig); - } -} diff --git a/android/app/src/main/java/com/anonymous/Assemblr/MainApplication.kt b/android/app/src/main/java/com/anonymous/Assemblr/MainApplication.kt new file mode 100644 index 0000000..b59a158 --- /dev/null +++ b/android/app/src/main/java/com/anonymous/Assemblr/MainApplication.kt @@ -0,0 +1,57 @@ +package com.anonymous.Assemblr + +import android.app.Application +import android.content.res.Configuration + +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.ReactHost +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.react.soloader.OpenSourceMergedSoMapping +import com.facebook.soloader.SoLoader + +import expo.modules.ApplicationLifecycleDispatcher +import expo.modules.ReactNativeHostWrapper +import com.asterinet.react.tcpsocket.TcpSocketPackage; +class MainApplication : Application(), ReactApplication { + + override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper( + this, + object : DefaultReactNativeHost(this) { + override fun getPackages(): List { + val packages = PackageList(this).packages + packages.add(PdfToBitmapPackage()) + packages.add(TcpSocketPackage()) + return packages + } + + override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + ) + + override val reactHost: ReactHost + get() = ReactNativeHostWrapper.createReactHost(applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + SoLoader.init(this, OpenSourceMergedSoMapping) + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + ApplicationLifecycleDispatcher.onApplicationCreate(this) + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig) + } +} diff --git a/android/app/src/main/java/com/anonymous/Assemblr/PdfToBitmapModule.kt b/android/app/src/main/java/com/anonymous/Assemblr/PdfToBitmapModule.kt new file mode 100644 index 0000000..2206a95 --- /dev/null +++ b/android/app/src/main/java/com/anonymous/Assemblr/PdfToBitmapModule.kt @@ -0,0 +1,67 @@ +package com.anonymous.Assemblr + + +import android.graphics.Bitmap +import android.graphics.pdf.PdfRenderer +import android.os.ParcelFileDescriptor +import android.util.Base64 +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContextBaseJavaModule +import com.facebook.react.bridge.ReactMethod +import com.facebook.react.bridge.WritableNativeArray +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.FileOutputStream +import androidx.core.graphics.createBitmap + +class PdfToBitmapModule(reactContext: ReactApplicationContext) : + ReactContextBaseJavaModule(reactContext) { + override fun getName(): String = "PdfToBitmap" + + @ReactMethod + fun convertPdfToBitmaps(pdfBase64: String, promise: Promise) { + try { + // Decode base64 PDF to byte array + val pdfBytes = Base64.decode(pdfBase64, Base64.DEFAULT) + + // Create temporary file for PDF + val tempFile = File.createTempFile("tempPdf", ".pdf", reactApplicationContext.cacheDir) + FileOutputStream(tempFile).use { fos -> + fos.write(pdfBytes) + } + + // Initialize PdfRenderer + val fd = ParcelFileDescriptor.open(tempFile, ParcelFileDescriptor.MODE_READ_ONLY) + val pdfRenderer = PdfRenderer(fd) + + // Convert each page to a bitmap + val bitmapBase64List = WritableNativeArray() + for (pageIndex in 0 until pdfRenderer.pageCount) { + val page = pdfRenderer.openPage(pageIndex) + val scaleFactor = if (page.width < 100) 100 else 5 + val bitmap = createBitmap(page.width * scaleFactor, page.height * scaleFactor) + page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY) + + // Convert bitmap to base64 + val stream = ByteArrayOutputStream() + bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream) + val byteArray = stream.toByteArray() + val base64String = Base64.encodeToString(byteArray, Base64.NO_WRAP) + bitmapBase64List.pushString(base64String) + + // Clean up + bitmap.recycle() + page.close() + } + + // Clean up renderer and file + pdfRenderer.close() + tempFile.delete() + + promise.resolve(bitmapBase64List) + } catch (e: Exception) { + promise.reject("PDF_CONVERSION_ERROR", "Failed to convert PDF to bitmaps: ${e.message}") + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/anonymous/Assemblr/PdfToBitmapPackage.kt b/android/app/src/main/java/com/anonymous/Assemblr/PdfToBitmapPackage.kt new file mode 100644 index 0000000..f0df33c --- /dev/null +++ b/android/app/src/main/java/com/anonymous/Assemblr/PdfToBitmapPackage.kt @@ -0,0 +1,16 @@ +package com.anonymous.Assemblr + +import com.facebook.react.ReactPackage +import com.facebook.react.bridge.NativeModule +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.uimanager.ViewManager + +class PdfToBitmapPackage : ReactPackage { + override fun createNativeModules(reactContext: ReactApplicationContext): List { + return listOf(PdfToBitmapModule(reactContext)) + } + + override fun createViewManagers(reactContext: ReactApplicationContext): List> { + return emptyList() + } +} \ No newline at end of file diff --git a/android/app/src/main/res/drawable-hdpi/splashscreen_image.png b/android/app/src/main/res/drawable-hdpi/splashscreen_image.png deleted file mode 100644 index c52c2c6..0000000 Binary files a/android/app/src/main/res/drawable-hdpi/splashscreen_image.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-hdpi/splashscreen_logo.png b/android/app/src/main/res/drawable-hdpi/splashscreen_logo.png new file mode 100644 index 0000000..0908137 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/splashscreen_logo.png differ diff --git a/android/app/src/main/res/drawable-mdpi/splashscreen_image.png b/android/app/src/main/res/drawable-mdpi/splashscreen_image.png deleted file mode 100644 index c52c2c6..0000000 Binary files a/android/app/src/main/res/drawable-mdpi/splashscreen_image.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-mdpi/splashscreen_logo.png b/android/app/src/main/res/drawable-mdpi/splashscreen_logo.png new file mode 100644 index 0000000..ac8a5bb Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/splashscreen_logo.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png b/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png deleted file mode 100644 index c52c2c6..0000000 Binary files a/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png b/android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png new file mode 100644 index 0000000..cec3361 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png b/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png deleted file mode 100644 index c52c2c6..0000000 Binary files a/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png b/android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png new file mode 100644 index 0000000..6c08a11 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png b/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png deleted file mode 100644 index c52c2c6..0000000 Binary files a/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png b/android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png new file mode 100644 index 0000000..fbe261e Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png differ diff --git a/android/app/src/main/res/drawable/splashscreen.xml b/android/app/src/main/res/drawable/ic_launcher_background.xml similarity index 59% rename from android/app/src/main/res/drawable/splashscreen.xml rename to android/app/src/main/res/drawable/ic_launcher_background.xml index c8568e1..883b2a0 100644 --- a/android/app/src/main/res/drawable/splashscreen.xml +++ b/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,3 +1,6 @@ + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable/rn_edit_text_material.xml b/android/app/src/main/res/drawable/rn_edit_text_material.xml index 73b37e4..5c25e72 100644 --- a/android/app/src/main/res/drawable/rn_edit_text_material.xml +++ b/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -17,7 +17,8 @@ android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material" android:insetRight="@dimen/abc_edit_text_inset_horizontal_material" android:insetTop="@dimen/abc_edit_text_inset_top_material" - android:insetBottom="@dimen/abc_edit_text_inset_bottom_material"> + android:insetBottom="@dimen/abc_edit_text_inset_bottom_material" + >