panpf / zoomimage

ZoomImage is a library designed for Compose Multiplatform and Android View for gesture zoom viewing of images, supported scale, pan, locate, rotation, and super-large image subsampling.
Apache License 2.0
195 stars 10 forks source link

Add support for iOS #19

Open hm-tamim opened 4 months ago

hm-tamim commented 4 months ago

Please add support for iOS target in Compose Multiplatform

panpf commented 4 months ago

It’s already in the plan, so stay tuned!

szczepanski-k commented 1 month ago

Hi @panpf , do you have any ETA for iOS support?

panpf commented 1 month ago

The alpha version will be released in about two months, because Sketch, the image loader that zoomimage relies on, is about to release a full platform version. After the release, we can start developing the iOS version of zoomimage.

kasem-sm commented 2 weeks ago

Hey. Any updates/eta on this please?

panpf commented 2 weeks ago

iOS support is in progress, please follow the progress of the dev branch

kasem-sm commented 2 weeks ago

Great. Can I try it locally? If yes, which modules should I import. Thanks!

panpf commented 2 weeks ago

Yes, please follow the steps below:

  1. Switch to the dev branch and update the latest code
  2. Execute ./gradlew publishToMavenLocal
  3. Then you can locally depend on the 1.1.0-SNAPSHOT version of the zoomimage-compose-sketch module
  4. Use the SketchZoomAsyncImage component to load and display the image
  5. Currently you need to depend on the 4.0.0-alpha03 version of sketch, which is being uploaded to the maven repository. If you cannot download the dependency at this time, please wait one to two hours and try again
kasem-sm commented 2 weeks ago

I'm getting Task 'publishToMavenLocal' not found in root project 'zoomimage' and its subprojects.

panpf commented 2 weeks ago

Sorry, there was a problem before, it works now, please update the code of the dev branch, I have tested it locally

kasem-sm commented 2 weeks ago

first impression is that it works great on iOS 🥹 Here's a screen recording - https://drive.google.com/file/d/1bFp8Hr9VswKPVP_GiUiwN-dSYNSaJn2a/view?usp=sharing

panpf commented 2 weeks ago

This is really good news, and I am glad that you have run it successfully.

At present, the integration of sketch 4 and coil3 has been completed, and you can choose the image loading framework you like.

Next, my work is to refactor the sample app and complete the unit test. When everything is ready, the alpha version can be released. It is expected to take 3 to 4 weeks. Please stay tuned.

szczepanski-k commented 2 weeks ago

That's really great news! @panpf Thank you for the update. I'm looking forward for the alpha version!

LOOHP commented 1 week ago

Hi, is support for Wasm Web also coming with this update?

panpf commented 1 week ago

The alpha version is expected to be released in about a week, which will support ios, js, and wasmJs

LOOHP commented 1 week ago

I've tried building it locally following the steps and including it in commonMain.

implementation("io.github.panpf.zoomimage:zoomimage-compose:1.1.0-SNAPSHOT")

(I also tried)

implementation("io.github.panpf.zoomimage:zoomimage-compose-sketch:1.1.0-SNAPSHOT")

While it compiles on Android perfectly, it couldn't compile on wasmJs.

> Task :composeApp:compileDevelopmentExecutableKotlinWasmJs FAILED
e: java.lang.NullPointerException: null cannot be cast to non-null type org.jetbrains.kotlin.descriptors.ClassDescriptor
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.findClass(WasmSymbols.kt:387)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.getClass$backend_wasm(WasmSymbols.kt:396)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.getIrClass(WasmSymbols.kt:416)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.getInternalClass(WasmSymbols.kt:417)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.access$getInternalClass(WasmSymbols.kt:32)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols$WasmReflectionSymbols.<init>(WasmSymbols.kt:64)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.<init>(WasmSymbols.kt:72)
    at org.jetbrains.kotlin.backend.wasm.WasmBackendContext.<init>(WasmBackendContext.kt:117)
    at org.jetbrains.kotlin.backend.wasm.WasmCompilerKt.compileToLoweredIr(wasmCompiler.kt:70)
    at org.jetbrains.kotlin.cli.js.K2JsIrCompiler.doExecute(K2JsIrCompiler.kt:361)
    at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:181)
    at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:72)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:104)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:48)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1523)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
    at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
    at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Unknown Source)
    at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Unknown Source)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.base/java.lang.Thread.run(Unknown Source)

java.lang.NullPointerException: null cannot be cast to non-null type org.jetbrains.kotlin.descriptors.ClassDescriptor
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.findClass(WasmSymbols.kt:387)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.getClass$backend_wasm(WasmSymbols.kt:396)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.getIrClass(WasmSymbols.kt:416)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.getInternalClass(WasmSymbols.kt:417)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.access$getInternalClass(WasmSymbols.kt:32)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols$WasmReflectionSymbols.<init>(WasmSymbols.kt:64)
    at org.jetbrains.kotlin.backend.wasm.WasmSymbols.<init>(WasmSymbols.kt:72)
    at org.jetbrains.kotlin.backend.wasm.WasmBackendContext.<init>(WasmBackendContext.kt:117)
    at org.jetbrains.kotlin.backend.wasm.WasmCompilerKt.compileToLoweredIr(wasmCompiler.kt:70)
    at org.jetbrains.kotlin.cli.js.K2JsIrCompiler.doExecute(K2JsIrCompiler.kt:361)
    at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:181)
    at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:72)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:104)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:48)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1523)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
    at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
    at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Unknown Source)
    at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Unknown Source)
    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.base/java.lang.Thread.run(Unknown Source)

Execution failed for task ':composeApp:compileDevelopmentExecutableKotlinWasmJs'.
> A failure occurred while executing org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction
   > Internal compiler error. See log for more details
panpf commented 1 week ago

I can't tell you directly what the problem is and how to solve it, because it's beyond my ability, and it should be the ability of the kmp team.

But I can tell you that my sample app can run normally, so there may be something wrong with your configuration or environment.

I suggest you try the following solutions to solve the problem:

  1. Download a new project template containing wasmJs from https://kmp.jetbrains.com and run it directly.

  2. After running successfully, import the dependency of zoomimage and write an example. This step should be fine.

  3. Finally, compare the configuration of your project to find out the problem

LOOHP commented 1 week ago

Thank you for the advice, I've managed to find the root of the problem. It was because I was using Kotlin 1.9.24 instead of 2.0.0. The library works well on wasmJs. However, the zoom controls with the mouse on the web browser are a bit confusing. Dragging in random directions sometimes registers as zoom while other times as panning. I also suggest adding the option to use the scroll wheel to zoom in/out as you do with things like Google Maps.

panpf commented 2 days ago

Version 1.1.0-alph01, which supports iOS, js, and wasmJS, has been released. You are welcome to try it and give us feedback.

https://github.com/panpf/zoomimage/releases/tag/1.1.0-alpha01

Next we will focus on optimizing experience issues and unit testing