Skip to content

Commit

Permalink
feat: add native picture viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreCapo committed Dec 28, 2023
1 parent 81a41e1 commit 2572168
Show file tree
Hide file tree
Showing 19 changed files with 15,181 additions and 31 deletions.
1 change: 1 addition & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,6 @@ dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'com.github.chrisbanes:PhotoView:565505d5cb84f5977771b5d2ccb7726338e77224'
}

6 changes: 5 additions & 1 deletion android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pictures">
package="com.pictures">

<application>
<activity android:name=".PictureViewerActivity" />
</application>
</manifest>
81 changes: 81 additions & 0 deletions android/src/main/java/com/pictures/PictureViewerActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.pictures

import android.app.Activity
import android.os.Bundle
import android.graphics.BitmapFactory
import android.graphics.Color
import android.view.Gravity
import android.widget.FrameLayout
import android.widget.ImageView
import com.github.chrisbanes.photoview.PhotoView
import java.net.HttpURLConnection
import java.net.URL

class PictureViewerActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Set the layout for the activity
// Create a LinearLayout
// Create a FrameLayout

val frameLayout = FrameLayout(this).apply {
layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
)
setBackgroundColor(Color.WHITE)
}

// Create and configure PhotoView
val imageUrl = intent.getStringExtra("imageUrl")
val imageView = PhotoView(this).apply {
layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
)
}

// Add PhotoView to FrameLayout
frameLayout.addView(imageView)

// Create and configure Close Button
val closeButton = ImageView(this).apply {
layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
).also {
it.gravity = Gravity.TOP or Gravity.END
it.setMargins(0, 30, 30, 0) // Adjust margins as needed
}
setImageResource(android.R.drawable.ic_menu_close_clear_cancel) // Use a suitable close icon
setOnClickListener {
finish() // Close the activity
}
}
closeButton.setColorFilter(Color.BLACK)

// Add Close Button to FrameLayout
frameLayout.addView(closeButton)

// Set FrameLayout as the content view
setContentView(frameLayout)

Thread {
try {
val url = URL(imageUrl)
val connection = url.openConnection() as HttpURLConnection
connection.doInput = true
connection.connect()
val inputStream = connection.inputStream
val bitmap = BitmapFactory.decodeStream(inputStream)

runOnUiThread {
imageView.setImageBitmap(bitmap)
}
} catch (e: Exception) {
e.printStackTrace()
// Handle exceptions
}
}.start()
}
}
9 changes: 7 additions & 2 deletions android/src/main/java/com/pictures/PicturesModule.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.pictures

import android.content.Intent
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
Expand All @@ -15,8 +16,12 @@ class PicturesModule(reactContext: ReactApplicationContext) :
// Example method
// See https://reactnative.dev/docs/native-modules-android
@ReactMethod
fun multiply(a: Double, b: Double, promise: Promise) {
promise.resolve(a * b)
fun openPictureViewer(url: String, promise: Promise) {
val intent = Intent(reactApplicationContext, PictureViewerActivity::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra("imageUrl", url)
reactApplicationContext.startActivity(intent)
promise.resolve(null)
}

companion object {
Expand Down
1 change: 1 addition & 0 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.pictures.PictureViewerActivity"></activity>
</application>
</manifest>
2 changes: 2 additions & 0 deletions example/ios/.xcode.env.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export NODE_BINARY=/Users/pierrecaporossi/.nvm/versions/node/v18.17.1/bin/node

32 changes: 26 additions & 6 deletions example/ios/PicturesExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@
"$(inherited)",
);
INFOPLIST_FILE = PicturesExampleTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -442,7 +442,7 @@
BUNDLE_LOADER = "$(TEST_HOST)";
COPY_PHASE_STRIP = NO;
INFOPLIST_FILE = PicturesExampleTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -466,8 +466,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 9A48KBL3Q4;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = PicturesExample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -493,7 +495,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 9A48KBL3Q4;
INFOPLIST_FILE = PicturesExample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -544,7 +548,7 @@
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
Expand All @@ -560,7 +564,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift,
"$(inherited)",
Expand All @@ -572,14 +576,22 @@
);
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1",
"-DFOLLY_CFG_NO_COROUTINES=1",
);
OTHER_LDFLAGS = (
"$(inherited)",
"-Wl",
"-ld_classic",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;
};
name = Debug;
};
Expand Down Expand Up @@ -616,7 +628,7 @@
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
Expand All @@ -625,7 +637,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift,
"$(inherited)",
Expand All @@ -636,14 +648,22 @@
"\"$(inherited)\"",
);
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1",
"-DFOLLY_CFG_NO_COROUTINES=1",
);
OTHER_LDFLAGS = (
"$(inherited)",
"-Wl",
"-ld_classic",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;
VALIDATE_PRODUCT = YES;
};
name = Release;
Expand Down
10 changes: 10 additions & 0 deletions example/ios/PicturesExample.xcworkspace/contents.xcworkspacedata

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
3 changes: 2 additions & 1 deletion example/ios/PicturesExample/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSAllowsLocalNetworking</key>
Expand All @@ -46,6 +45,8 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app wants to access your photo gallery</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
Expand Down
Loading

0 comments on commit 2572168

Please sign in to comment.