UI::Notification improvement

I’ve just met UI:Notification and Its great!
Notification

But I’ve 3 suggestions:
1- It lasts too short on screen (like 3s). There should be a time param;
2- We should be able to break/jump message line with “\n”;
3- The top bar color should be custom.

Why do I want to use it?
a) UI.messagebox is too big and modal wich usually annoys users and can’t stack;
b) UI::HtmlDialog is just too big/crude for this application;
c) UI:Notification fits rlly nice on UI style, isn’t modal and its perfect for notifications that u may preffer to ignore (such operation end message; during operation partial reports, hints/advices, manipulative religious speeches from selective karens just bc it’s convenient to their agenda);
d) I’ve no idea how to develop an advanced custom UI such “Curic Pie Menus” (would love to hear advices on it).


But even that SU team adds my suggestions, it would probly break backwards compatibility :frowning:
So in order to have a better UI:Notification in older SU we must find a workaround.

So I’ve made this:

module Taxsola
	module UI_notification_test
		require 'sketchup.rb'
		require 'extensions.rb'

		@extension = SketchupExtension.new('Plugin name', 'core.rb')
		@Stats = 0

		@message = "SUCESS!\r\nRuntime: 45s"
		@notification = UI::Notification.new(@extension, @message)
		@notification.on_accept("Ok") { puts "Closes"; @Stats = 1; }
		@notification.on_dismiss("Statistics") { puts "Shows statistics"; @Stats = 1; }
		@notification.show

		@Timer = UI.start_timer(4,true) {
			if (@Stats == 1)
				UI.stop_timer(@Timer)
			else
				@notification.show #unless @notification.shown? <<< there should be this feature so they dont stack when mouse is over it.
			end
		}
	end
end

Wich is almost Okay, except it does stack flooding if you keep the mouse over the notification.

Questions:
Is there a way to check if the notification is visible? ie. “object.visible?” or “object.shown?”
Is there a way to check if the mouse is above the notification?
is there a way to show/hide it instantly/without transition? so we could make it return seamlessly.

Final considerations:
Yes, we could set a time range where it would keep returning.

Thanks for reading! :v:


Related topic:

Do not define instance variables in the top level ObjectSpace.

The duration was extended to 10 seconds in the 2021.1 release.

What version are you running ?

The documentation for the class constructor method is clear, use \r\n for line breaks.

This is the caption bar color controlled by the OS, which is set by the end user.
It is always best to honor the user’s settings. (There are better things to improve.)

It’s been discussed. There is potential for it to be misused (advertising, etc.)

I like the default at 10 secs. It would nice if the user could adjust that time, and/or set a maximum.

3 Likes

I moved the topic to Ruby API category. :innocent:

Please see also:
https://github.com/SketchUp/api-issue-tracker/issues?q=is%3Aissue+is%3Aopen+UI%3A%3Anotification+
…and please report API related request there (too)

1 Like

In what duration would you have liked the notification to appear at?

What kind of messages are you looking to display?

1 Like

SU18.0 pro on Win11

Thanks, I forgot. Bad habits… its fixed now.

Thanks. I assumed it was the same as messagebox, my bad.

Thats great to know, thanks again. 10s sounds good enough to me. (custom would be even better)
Now I just gotta find a workaround for prior versions :l

I don’t think it should be a reason to fix its time. I mean, devs still could do ads with:
htmldialog, messagebox, note, status_text, style, external links, even sound ads…
I know that notifications looks like popups from some www.freemoviesonline.cow but I see its potential to be the inverse of it, by avoinding annoying stuff such most messagebox.
obs: unless theres security/privacy reasons.

I don’t think so in this case.
Take a look at Modus (SU UI guideline) pallete:

So the color should be decided by the use case (by devs).
Not total custom, but still some range to choose from.
I know its a small detail, but I think it would look more integrated/professional.

Thanks. Gonna do that when I get a final/mature suggestion.
Edit: Dan has just posted a dedicated thread on the matter:

10s sounds great for most use cases. The problem now is prior SU versions :confused:

I think I would use it for something like:

ON INSTALLATION:
1) Tax's extension has been installed! Open docs?

ON START UP:
1) Your license ends in 3 days. Upgrade?
2) Theres an update for Tax's extension. More info?
3) Welcome again, theres 2 new Square one videos. Visit it? <- Optional start up feature

ON OPERATION PROCESS:
1) There should be 3 selected objects for this operation to run.
2) You've entered wrong input format! Only numbers are allowed. More info?
3) Here is the partial result! cancel operation? <- operation pause, if no response it proceeds normally
4) Hey man, I've finished the task! Do you want some statistics or nah? take or leave it.

ON OBSERVERS:
1) Tax's extension has been disabled.
2) Measure tool selected! "See tutorial" | "cancel tutorial notifications"
3) Too many objects on top space. Wanna learn how to use groups?
4) You've copied same object twice, run an array tool?
5) Group opened, theres 3 objects inside.
6) Model has been saved (50mb).

its just like:

In my very personal opinion, most of the notifications listed in your post are unnecessary (spam) to me and there should be a button (setting) to completely disable such notifications.

4 Likes

Agree, and a few of these sounds like you would expect user input - for instance in failure cases. In which case a messagebox is more appropriate.

2 Likes

Thanks for your feedbacks.

I dont think they are spam, but ll make sure theres a disable button for most of them.

And actually, none of my listed examples needs an answer to proceed. You can read the notif. (if u want) and let it go.
No failure case strictly needs an answer to proceed. Bc if its failed then its done! it doesnt need any answer. it only needs you to change the inputs, and for that u only need a notification.

I only plan to use msgbox if it rlly needs an answer or theres too much too read (MB_MULTILINE is perfect for reports).

Other than that, I’ve heard many times that msgbox are annoying. It interrupts your workflow, forces u to read and take an action wich in many cases is a MB_OK.

If not UI:Notification… SU still needs some type of user friendly notification (maybe log as Dan has suggested on github)
Windows, Ubuntu, Android, Autocad, Blender, Unreal, VScode, Xbox/PlayStation, Steam… many successful examples of this feature.

If I’m using it wrong, what would be the good use cases for UI:Notification on SU?
@dezmo @tt_su

I prefer if notification will appear at the left-side of the status bar, or Tooltip, for “You’ve entered wrong input format!” kind of notification. The others should be disabled by default, allow only via settings.

I do not like the UI::Notification popup at all, it is annoying, distracting, and have not been polished enough, does not have a right behaviour. It is behaving like the system notification but using SketchUp UI design. (at least on Windows)
Currently e.g. the integrated Extension Manager using it “officially,” but that does not respect my General Preferences where I disabled “Allow checking for updates”.
The information is redundant…

...or even wrong sometimes.

Wrong notification on SU2021. In my corporate laptop some downloads are restricted:
EMnotwrong

Actually, this kind of animated popup very much reminds me the current trends on the internet, where the web designer - or their employers - thinks these popups are “very good” for us…
“I only wanted good for you!”

Please let me decide for myself what is good for me:

I’m tired of the constant clicking or the visual disturbance!

  • No, I don’t want to subscribe.
  • No, I don’t want an update.
  • No, I do not want to download your f…ing mobile app.
  • Yes, I know you are using cookies, you told me last time.
  • No, I do not want you to store my data in cookies.
  • No, I don’t want to register.
  • No, I don’t want to use the f…ing popup help assistant.
  • No, I don’t think it is a f…ing important news for me.

In exaggeration:
If I have read the “Notification”, I will call you and let you know that I have read it. If you find it important to notify me, you will certainly appreciate it if I notify you that I have read your notification. Right? :wink:

1 Like

Agreed, also the new changes breaks consistency if ur coding for SU17+.

I do think they’re nice and discreet but it doesnt give u a direct action option.
If user needs +info, ur keeping them +1 step farther from solution.

msgbox is too intrusive, demanding action. (deciding things for you)
status is too evasive, not providing support link. (to hide info is also a form of control)
There should be a balance, for optional direct actions wich u may preffer to ignore.

You may hate it, but Trimble seems to love it :grin::
1- Alerts | Trimble Modus Bootstrap Developer Guide
2- Toasts | Trimble Modus Bootstrap Developer Guide
3- Messages | Trimble Modus Bootstrap Developer Guide

But we’r getting off topic, the point is how to make it work.


I’ve left aside UI:notification aproach since its bad at SU17 and I cant fix it but make it glitchy.
Now I’m trying to use HtmlDialog to mimic its function:

module Taxsola
	#This is the function wich stays in the library
	def self.Notification(title, message, b1, b2)
		@dialog_box = UI::HtmlDialog.new({
			:dialog_title => title.to_s,
			:preferences_key => "com.sample.plugin",
			:resizable => false,
			:style => UI::HtmlDialog::STYLE_DIALOG
		})

		html = "<!DOCTYPE html>
			<html>
			  <link href='https://sketchup.github.io/modus-for-sketchup-extensions/modus.min.css' rel='stylesheet'>
				<script>function Input(val) {sketchup.Input(val);}</script>
			  <body>

				<div class='modal-content' style='height: 100%; border-style: none;'><div class='modal-footer'>
					<h5 id='a' style='position: absolute; top: 15px; left: 10px;'>"+message.to_s+"</h5><br>
					<button type='button' class='btn btn-sm btn-outline-dark' onclick='Input(0);'>"+b1.to_s+"</button>
					<button type='button' class='btn btn-sm btn-primary' onclick='Input(1)'>"+b2.to_s+"</button>
				</div></div>

			  </body>
			</html>"

		@dialog_box.set_html(html)
		@dialog_box.set_size(400, 100)
		@dialog_box.show

		@result = "no answer from callback"
		@start_time = Time.now
		@run_time = 0
		
		@dialog_box.add_action_callback("Input") { |action_context, x| @result = x;}

		until (@result != "no answer from callback") or (@run_time >= 3)
			@run_time = Time.now - @start_time
			sleep 1 # THE PROBLEM IS HERE <<< <<< <<<
		end

		@dialog_box.close
		return @result
	end

	module UI_notification_test2
		#This is how dev would usually call the function
		#Notification(title, message, button1, button2) => return 0 (button1) or 1 (button2)
		@input = Taxsola.Notification("Notification Alert UI", "Tax Engineering v10.9 is available!", "Demiss", "View")
		puts @input
	end
end

The problem is:
HtmlDialog is freezing when I try to wait for callback to run once.
If the function dont wait for callback to run, then it will end without returning user input.

Question: How can it wait for callback to run once before ending/returning the function? any other aproach?


Thanks for all ur previous feedbacks :v:

There are many ways to structure this code. Here is one option.

module Taxsola
  # class Notification is an HtmlDialog that knows how to close itself after 'delay' seconds
  #
  class Notification
    attr_reader :dialog_box
    
    def initialize( title, html, delay = 3 )
    
      params = {
        :dialog_title => title.to_s,
        :preferences_key => "com.sample.plugin",
        :resizable => false,
        :style => UI::HtmlDialog::STYLE_DIALOG
      }
      
      @dialog_box = UI::HtmlDialog.new( params )
      @dialog_box.set_html( html )
      @dialog_box.set_size( 400, 100 )
      @dialog_box.show
       UI.start_timer( delay, false ) { @dialog_box.close }

    end # initialize
  end #notification
end

# For flexability the HTML content and actions are setup by the calling method.
#
module SomeModule
  def self.show_available_dialog()
    message = "Tax Engineering v10.9 is available!"
    label1 = 'Dismiss'
    label2 = 'View'
    
    html = "<!DOCTYPE html>
      <html>
        <link href='https://sketchup.github.io/modus-for-sketchup-extensions/modus.min.css' rel='stylesheet'>
        <script>function Input(val) {sketchup.Input(val);}</script>
        <body>

        <div class='modal-content' style='height: 100%; border-style: none;'><div class='modal-footer'>
          <h5 id='a' style='position: absolute; top: 15px; left: 10px;'>" + message.to_s + "</h5><br>
          <button type='button' class='btn btn-sm btn-outline-dark' onclick='Input(0);'>" + label1 + "</button>
          <button type='button' class='btn btn-sm btn-primary' onclick='Input(1)'>" + label2 + "</button>
        </div></div>
        </body>
      </html>"

    # create and show the dialog
    a_notification = Taxsola::Notification.new( "Notification Alert UI", html )

    # add callback routines
    a_notification.dialog_box.add_action_callback("Input") { |action_context, x|
      case x
        when 0
           p 'Dismiss'
        when 1
          p 'View'
      end
      a_notification.dialog_box.close
    }
  end
end

SomeModule.show_available_dialog()




3 Likes

:astonished: u made it look so easy. Thanks a lot!

Just out of curiosity, what makes it work?
Timer and callback must be separated?
Timer inside a class doesn’t freeze SU?

Thx again.

We don’t currently have any UX guidelines on notifications, but I’d describe them as a “hey btw” type of messages. Like “Hey, btw, there is a new update” or “Hey, btw, your license will expire next week”. It’s the kind of messages that are not crucial and not urgent. If the user happens to look away no harm should be done. If they instead see the message the next day, or the day after that, it provides the same value to them.

Typically this kind of message is not used for feedback on direct user input, such as an invalid format. If the user gets distracted by something, finishes what they are typing, press enter and then turn away to talk to a coworker or something, they shouldn’t miss out on a message saying what they enter couldn’t be used. A messagebox is in my view more appropriate.

If the timout is customizable I think it should be an end user setting, not an API parameter. The time needed varies by the reading speed of the user, not the reading speed of the developer. If you want to show more information than typical for a notification or ask a question that takes more time to understand and respond to than typical for a notification, I’d recommend using another UI such as a messagebox to give the user that time, not using a notification that breaks the expectations of what a notification is.

I’d also recommend to keep the amount of messaging down to the absolute minimum. Being bombarded by messages you need to read is stressful and distracting. If the user uninstalled an extension, they know they uninstalled the extension. There is no need to tell them. Tool tutorials can be provided in the Instructor (which the user can opt out of by closing it). If you want to see the number of objects in a group you can select all and look in Entity Info, or have a button you press to get that information, or have a dialog optionally open that dynamically shows the number of entities in the active entities. You don’t need that information popping up when opening a group. The time it took to finish an operation might be suitable for a notification, but I don’t actually know what an end user would do with that information. It can surely be useful for a developer when optimizing, but as a user you mostly care that the operation is finished and you can keep modeling, not the number of seconds it took. SketchUp itself doesn’t display the time it took to e.g. save the model.

4 Likes

Many thanks to Julia for her well written response to this topic. I, like all of the other responders, feel that Notifications are only appropriate in a few situations; although, in which situations they are appropriate has not been determined.

To your question “Why does this work?”
I did some spying on the Windows OS and noticed that the HtmlDialog window (the rectangle you see on the screen) is serviced by the same thread that is running the Sketchup application. This is the same thread that is running the ‘until’ loop in your Ruby example code. The result is that the HtmlDialog is waiting for you to return to Sketchup from Ruby before it is called upon to update the screen representation of itself. I hope that makes sense.

2 Likes

Hey Eneroth, thanks for clarifying and pointing the good usage.
Guess I can see better now.

Gonna make it my personal guidelines:

Rules/Requirements:

  • “hey btw, not crucial and not urgent”
  • “the day after that, it provides the same value”
  • timout as user setting
  • minimum necessary

Notif. applications:

  • Installation with ‘wanna see docs?’;
  • Updates info with ‘visit website’; (optional)
  • License info with ‘upgrade?’; (optional)

MsgBox for:

  • MB_YESNO for Input verification errors with “wanna see docs?”;
  • Long to read/decide;
  • Decision is necessary to proceed.

Corrections to do on my extension:

  • ‘Sucess’ as UI.beep only (maybe custom sound);
  • Runtime/Reports/Statistics shown on console only.

obs: When I update my extension with these features, I link it here so u guys can take a look and give more feedbacks if u want.

Thanks you all.

Makes all sense now. Thanks again.