Import load_from_url problem in Windows and macOS

Greetings! I use two standard examples https://ruby.sketchup.com/Sketchup/DefinitionList.html#load_from_url-instance_method and https://ruby.sketchup.com/UI/HtmlDialog.html.

When I use load_from_url in the Ruby console. Everything is ok, I get the model to be located in the project.

But, after I try to wrap this in the interface then on Windows - everything is fine. I get the model.
But on macOS, no. In the console, I get a message that a model request is going on, and the whole program hangs. I tried to find a solution, but it kept saying I used the wrong method, without class LoadHandler. Well, I took that class and the result is the same.

Below is a sample code for window and ruby call.

module UPLOAD
  class LoadHandler
    attr_accessor :error

    def onPercentChange(percent)
      Sketchup::set_status_text("loading: #{percent.round}%")
    end

    def cancelled?
      # You could, for example, show a messagebox after X seconds asking if the
      # user wants to cancel the download. If this method returns true, then
      # the download cancels.
      return false
    end

    def onSuccess
      Sketchup::set_status_text('')
    end

    def onFailure(error_message)
      self.error = error_message
      Sketchup::set_status_text('')
    end
  end
  #Window
  def self.WND
    dialog = UI::HtmlDialog.new(
      {
        :dialog_title => "Dialog Example",
        :preferences_key => "com.sample.plugin",
        :scrollable => true,
        :resizable => true,
        :width => 600,
        :height => 400,
        :left => 100,
        :top => 100,
        :min_width => 50,
        :min_height => 50,
        :max_width =>1000,
        :max_height => 1000,
        :style => UI::HtmlDialog::STYLE_DIALOG
      })
    dialog.set_file(File.join(__dir__,'main.html'))
    dialog.show
    dialog.add_action_callback("dc") { |action_context, url|
      puts 'JavaScript return #{url}'
      #url = '#{url}'
	  model = Sketchup.active_model
	  load_handler = LoadHandler.new
	  definition = model.definitions.load_from_url(url, load_handler)
	  model.place_component(definition) #place by mouse
    if definition.nil?
      puts "Error: #{load_handler.error}"
    else
      puts "Status: Done}"
    end

    }
  end
  #Downloader

  toolbar = UI::Toolbar.new "Test"
  # This command displays Hello World on the screen when clicked
  cmd = UI::Command.new("Test") {
    UPLOAD::WND()
  }
  cmd.small_icon = "ToolPencilSmall.png"
  cmd.large_icon = "ToolPencilLarge.png"
  toolbar = toolbar.add_item cmd
  toolbar.show
end

external HTML

    <html lang="en">
    <head>
        <!-- semantic -->
        <meta charset="utf-8">
        <title>Upload tester cross OS</title>
    </head>
    <body class="catalog">
    <!-- <h1>Blanc kitchen catalog</h1>
    <br /> -->
    <script>
    		function dc1(val) {
    		sketchup.dc(val);
    		console.log(val);
    		  }
          </script>
        <b>Hello world!</b>
        <br/>
        <button id="https://3dwarehouse.sketchup.com/warehouse/v1.0/entities/c2fcfb40-7bc9-4831-8f4e-ba63236d1220/binaries/s21?download=true&recordEvent=true" onclick="dc1(this.id)">Download 3dwarhouse</button>
    <br/>
    <a id="https://3dwarehouse.sketchup.com/warehouse/v1.0/entities/c2fcfb40-7bc9-4831-8f4e-ba63236d1220/binaries/s21?download=true&recordEvent=true" onclick="dc1(this.id)">Not button 3dwarhouse</a>
    </body>
    </html>

I would suggest you add all action callbacks to html dialog objects before you call the show method.

I don’t have a Mac so I can’t test that for you. Sorry.


Although Ruby is forgiving, there are conventions to follow.

ALL_CAPS are constants that point at values or objects, except modules, classes and methods.

SnakeCase are constants that point at module and class objects.
(There are very special rules for short names that are acronyms, like UI, CSV, JSON, etc.)

lower_case are reference names that point at method objects.

snx,
I try to change position dialog.add_action_callback before dialog.show. Sorry, or i not understand what you mean, my level not god.
Not help. It’s sample and my other version I use lower_case in name.

Tried to rewrite the code and generally still try out the mechanics. Indeed, the basic code from the documentation works.

Further, as soon as I add a UI HTML call, the program freezes. If the call comes from the code, everything is fine.

Next I added PUTS, suddenly at some point in the code there is an error. But here, too, nothing, all the variables work as they should.

I even rewrote the code, splitting it in two modules, one window call and one file load call and got exactly the same thing. After processing, the program hangs on its head.

But, what I noticed is strange. If I use set_html instead of set_file, the code works fine. That’s what led me to believe that it is in the work with the connected file is the problem, for this reason, and I hung alerts to check whether everything is transmitted correctly.

Now I think, about not very nice variant.
Make branch “if-else” for windows and macOS, where for the first use set_file, for the second set_html. It’s not nice and it’s not clear.

Maybe the problem is some little thing I don’t see. Unfortunately I could not find examples of such a code on the GitHub, working both on macOS and on Windows.

The gist is kind of simple. Create a window, open a file there, get the value and by the value to load into the project.

At top of extension module …

WIN = Sketchup.platform == :platform_win
MAC = !WIN

Further down in code …

if WIN
  # do it one way
else
  # do it a different way
end

You should probably attach callbacks before calling either of these methods, and #show after these methods. (Ie, call #show last.)

1 Like

Yes, I try rebuild, and call Callback befor show.

load_handler require from external file.

It’s not help. Sketchup freeze anyway

module Darwin
  def self.Catalog
    dialog = UI::HtmlDialog.new(
      {
        :dialog_title => "Dialog Example",
        :preferences_key => "com.sample.plugin",
        :scrollable => true,
        :resizable => true,
        :width => 300,
        :height => 200,
        :left => 100,
        :top => 100,
        :min_width => 50,
        :min_height => 50,
        :style => UI::HtmlDialog::STYLE_DIALOG
      })
    dialog.add_action_callback("say") { |action_context, link_download|
      puts "Why try download #{link_download}"
      url = link_download
      model = Sketchup.active_model
      load_handler = LoadHandler.new
      definition = model.definitions.load_from_url(url, load_handler)
      return unless definition # good practice
      model.place_component(definition) #place by mouse
      if definition.nil?
        puts "Error: #{load_handler.error}"
      end
    }
    html = "
    <!DOCTYPE html>
    <html>
    <head>
    <title>Test Dialog
    </title>
    </head>
    <h1>Draw a Box from a HtmlDialog</h1>
    <script>
    function skp(val) {
       sketchup.say(val, {
            onCompleted: function() {
                console.log('Ruby side done.');
            }})
    }
    </script>
    <body>
    <b>Hello world!</b><br>
    <a id='https://3dwarehouse.sketchup.com/warehouse/v1.0/entities/c2fcfb40-7bc9-4831-8f4e-ba63236d1220/binaries/s21?download=true&recordEvent=true' onclick='skp(this.id)'>Download</a>
    </body>
    "
    dialog.set_html(html)
    dialog.center
    dialog.show
  end
end

Another thing I noticed is that if the component insertion code is called from the sketchup console - everything is fine. If the code is called, for example, through a third-party plugin ruby console. Then similarly the program freeze.

There is a suspicion that the problem with rights. Okay, I gave the program access rights to the drive, as well checked the rights to the folder plugins and directly to my plugin. Everything is also normal.

I get the impression that the problem is not really in the code. And something with rights, because using load_from_url, I use a class that at least somehow should pass the load status.

Actually, what I said is not true. You can reload a HTML string or a file at anytime even after showing the window.

I do it quite often to refresh the dialog display.


Back to the original quandary, sometimes there have been reported issues with set_file as it seems to copy the file to the user’s local temporary path and then loads it from there.

I say be sure that permissions are set correctly for the user temp path and perhaps see if there are any non-latin characters in the pathname.

I never use these 3rd party web dialog based “consoles” or editors. They create more issues then they solve. In my opinion, they are only good for running single statements or very small snippets.

Please do not use this as a namespace. It is an Apple trademark for their operating system kernel, and could cause confusion.


I found a few issues with your code:

  1. You cannot use return within a block. It will cause LocalJumpError exception.
    You can only return from a method. (Ie, you are returning from the call to the place in the code that the method was called from.)
    To “short-circuit” and “break out” of a block, you use a break a statement.

  2. Basically you did not heed the warnings in the API documentation for using HtmlDialog objects in the constructor details. Persistent references are needed so that dialogs remain viable.

The following example works for me both when pasted into the console, or loaded from the file when SketchUp starts.

GwynnBleiidd_Catalog_main.rb (5.0 KB)

I also made some changes:

a. I added a PLUGIN_KEY constant for use when saving default options and the Html dialog properties. (The docs tell you to use a unique key when calling the dialog constructor method.)

b. Overhauled the HTML document as it was out of order, and had closing tags missing, etc.
Ie, the <h1> element was not in the <body>, … etc,.

c. Added some style to the HTML to get a pointer hand cursor on the link.
Since, your not using an href attribute for the <a> element, I changed it to a simple <div>.

d. Renamed the "say" callback to "load".

e. Added a "ready" callback to the Ruby and a JS function to notify the Ruby-side when the dialog’s document is done rendering. (You’ll likely need this in the future as the web documents get more complex.)

f. Moved the download URL (as a format string) into a local constant with a %{id} replaceable parameter. The component 3DW id is now all that is held in the HTML links and all that needs to be passed back to the Ruby-side. Once comp_id is passed back to the load callback block, it is stuffed into the %{id} replaceable parameter using a call to String#%(). Ie …

url = URL % { :id => comp_id }

This is much better if the 3DW download URL or it’s parameters change in the future. You need only edit the URL constant definition at the top of the module, rather than many many places within HTML documents.

g. Reordered the definition test in the load callback to avoid the need for a break.

h. I also added a 30 second cancel limit just in case of a freeze up during download. (Not sure it will work, as the docs do not say when the cancelled? callback is called in the scheme of LoadHandler things.)


The code currently outputs information to the console, but in practice you would likely show message boxes to the user when a download fails.

1 Like

Thank you very much, such an extended example helped me to understand some things.

With macOS, the situation is the same. Checked the permissions for temporary directories, everything is basic there and it won’t let me change it. Accordingly, I did not touch, because the average user will not for the sake of the plugin to do more serious manipulations.

Okay … back to the issue …

Do you see any changing percentages on the status bar ?

Can you try with another model id from the 3DW ?

And what MacOS and SketchUp version ? I don’t have a MAc so cannot test for you.

No. Program freeze fully

No new, i try download from direct url on other hosting.

SU 2021, and try on two different macbook pro. MacOS i think have last update.

OK, then it’s time to open a formal issue in the API tracker …
Attach a copy of the test file I posted.

Thank you, I made a ticket.

I guess the topic can be closed. If anyone is interested in how this will end, you can track it in the ticket load_from_url on macOs completely kills the application · Issue #633 · SketchUp/api-issue-tracker · GitHub.