Jump to content

Applescript runs 5 slower in Alfred and as application than in Scripteditor


Recommended Posts

Hi!

I've found a great script online (credits are in comment in the script) that allows me to set a reminder for an email. When I execute it from the Scripteditor or use it as a service in Mail, it works instantaneously. But when I add it to Alfred as an applescript, or run it as an application, it takes 5 seconds to execute...

Any ideas how I might get the same performance from Alfred?

PS: I'm not a programmer but I have some limited coding experience.

 

#
# Title: Create reminder from selected Mail
# By Michael Kummer and partly based on various code snippets I found online
# michaelkummer.com
# You can use the source as you wish but do so at your own risk
# Have a backup of your data to avoid accidental loss
# Last update: March 18th, 2014
# Version: 0.1
# Tested on OS X 10.9.2 Mavericks
#
# Description
# When installed as a Service, this AppleScript script can be used to automatically create a reminder (in pre-defined Reminder lists)
# from a selected email and flag the email.
# If you run the script against an email that matches an existing reminder it can mark the reminder as completed and clear the flag in Mail
#
# Contributors and sources
# Rick0713 at https://discussions.apple.com/thread/3435695?start=30&tstart=0
# http://www.macosxautomation.com/applescript/sbrt/sbrt-06.html

# Set this according to your email account names and Reminder's lists
set WorkAccountName to "Exchange"
set WorkRemindersList to "Work"
set PersonalAccountName to "iCloud"
set PersonalRemindersList to "Personal"
# On my machine 5 is the Purple flag, which is the color I would like to use for mails flagged as Reminder
set FlagIndex to 5

tell application "Mail"

set theSelection to selection
# do nothing if no email is selected in Mail
try
set theMessage to item 1 of theSelection
on error
return
end try

set theSubject to theMessage's subject
# Make sure reminder doesn't already exist so we don't create duplicates
tell application "Reminders"

set theNeedlesName to name of reminders whose name is theSubject and completed is false
if theNeedlesName is not {} then
# make sure dialog is in focus when called as a service
# without the below, Mail would be the active application
tell me
activate
end tell
set theButton to button returned of (display dialog "The selected email matches an existing reminder: " & theNeedlesName & ". Would you like to mark the reminder as complete and clear any remaining flags of this message?" with title "Create Reminder from E-Mail" buttons {"Mark complete", "Cancel"} default button 1)

if theButton is "Mark complete" then
tell application "Mail"
# unflag email/message
set flag index of theMessage to -1
end tell
# find correct reminder based on subject and mark as complete
set theNeedle to last reminder whose name is theSubject and completed is false
set completed of theNeedle to true
return
else if the_button is "Cancel" then
return
end if

end if
end tell

# present user with a list of follow-up times (in minutes)
(choose from list {"Tomorrow", "2 Days", "End of Week", "1 Week", "1 Month", "3 Months"} default items "End of Week" OK button name "Create" with prompt "Set follow-up time" with title "Create Reminder from E-Mail")

set reminderDate to result as rich text

# Exit if user clicks Cancel
if reminderDate is "false" then return

if reminderDate = "Tomorrow" then
# add 1 day and set time to 9h into the day = 9am
set remindMeDate to (current date) + 1 * days
set time of remindMeDate to 60 * 60 * 9

else if reminderDate = "2 Days" then

set remindMeDate to (current date) + 2880 * minutes

else if reminderDate = "End of Week" then
# end of week means Thursday in terms of reminders
# get the current day of the week
set curWeekDay to weekday of (current date) as string
if curWeekDay = "Monday" then
set remindMeDate to (current date) + 3 * days
else if curWeekDay = "Tuesday" then
set remindMeDate to (current date) + 2 * days
else if curWeekDay = "Wednesday" then
set remindMeDate to (current date) + 1 * days
# if it's Thursday, I'll set the reminder for Friday
else if curWeekDay = "Thursday" then
set remindMeDate to (current date) + 1 * days
# if it's Friday I'll set the reminder for Thursday next week
else if curWeekDay = "Friday" then
set remindMeDate to (current date) + 6 * days
end if

set time of remindMeDate to 60 * 60 * 9

else if reminderDate = "1 Week" then

set remindMeDate to (current date) + 10080 * minutes

else if reminderDate = "1 Month" then

set remindMeDate to (current date) + 43200 * minutes

else if reminderDate = "3 Months" then

set remindMeDate to (current date) + 129600 * minutes

end if

# Flag selected email/message in Mail
set flag index of theMessage to FlagIndex

# Get the unique identifier (ID) of selected email/message
set theOrigMessageId to theMessage's message id

#we need to encode % with %25 because otherwise the URL will be screwed up in Reminders and you won't be able to just click on it to open the linked message in Mail
set theUrl to {"message:%3C" & my replaceText(theOrigMessageId, "%", "%25") & "%3E"}

# determine correct Reminder's list based on account the email/message is in
if name of account of mailbox of theMessage is WorkAccountName then
set RemindersList to WorkRemindersList
else if name of account of mailbox of theMessage is PersonalAccountName then
set RemindersList to PersonalRemindersList
else
#default list name in Reminders
set RemindersList to "Reminders"
end if

end tell

tell application "Reminders"

tell list RemindersList
# create new reminder with proper due date, subject name and the URL linking to the email in Mail
make new reminder with properties {name:theSubject, remind me date:remindMeDate, body:theUrl}

end tell

end tell

# string replace function
# used to replace % with %25
on replaceText(subject, find, replace)
set prevTIDs to text item delimiters of AppleScript
set text item delimiters of AppleScript to find
set subject to text items of subject

set text item delimiters of AppleScript to replace
set subject to "" & subject
set text item delimiters of AppleScript to prevTIDs

return subject
end replaceText



 

Link to comment

The AppleScript itself by Michael Kummer is a functionally-good script and undoubtedly extremely useful, but it's pretty terribly written and has a few inefficiencies in its code.  I doubt it will account for 5 seconds, but I've refactored (of sorts) the code to make it more articulate and efficient, below.


How have you implemented the above AppleScript into an Alfred workflow ?  Do you have a screenshot of the workflow or the workflow itself ?  When I implemented my version of the script, I did so in this fashion:

 

image.jpeg.cfb9394fdd2f1621c9049d423bb2186f.jpeg

 

and the script ran instantaneously. 

 

System info: AppleScript version: 2.7  System version: 10.13.6  Alfred version: 3.7

 

 

# Set this according to your email account names and Reminder's lists

set WorkAccountName to "Exchange"

set WorkRemindersList to "Work"

set PersonalAccountName to "iCloud"

set PersonalRemindersList to "Personal"

# On my machine 5 is the Purple flag, which is the color I would like to use for mails flagged as Reminder

set FlagIndex to 5

 

tell application "Mail"

        # do nothing if no email is selected in Mail

        set [theMessage] to the selection & {null}

        if theMessage = null then return

        

        set theSubject to theMessage's subject

end tell

 

# Make sure reminder doesn't already exist so we don't create duplicates

tell application "Reminders" to set needle to a reference to ¬

        (the last reminder whose name = theSubject and completed = false)

 

if the needle exists then

        tell the button returned of (display dialog contents of

                "The selected email matches an existing reminder: ", ¬

                needle's name, ". Would you like to mark the reminder as ", ¬

                "complete and clear any remaining flags of this message?"] ¬

                as text with title ["Create Reminder from E-Mail"] ¬

                buttons ["Mark complete", "Cancel"] ¬

                default button 1) to if it = "Cancel" then return

        

        # unflag email/message

        tell application "Mail" to set flag index of theMessage to -1

        

        # find correct reminder based on subject and mark as complete

        tell application "Reminders" to set completed of the needle to true

        

        return

end if

 

# present user with a list of follow-up times (in minutes)

set [reminderDate] to {} & (choose from list

        "Tomorrow", "2 Days", "End of Week", ¬

        "1 Week", "1 Month", "3 Months"] ¬

        default items ("End of Week") ¬

        OK button name ("Create") ¬

        with prompt ("Set follow-up time") ¬

        with title ("Create Reminder from E-Mail"))

 

# Exit if user clicks Cancel

if reminderDate = false then return

 

if reminderDate = "Tomorrow" then

        set remindMeDate to (current date) + 1 * days

else if reminderDate = "2 Days" then

        set remindMeDate to (current date) + 2 * days

else if reminderDate = "End of Week" then

        # end of week means Thursday in terms of reminders

        # set the reminder for Thursday, except:

        # if it's Thursday, set the reminder for Friday

        # if it's Friday, set the reminder for Thursday next week

        set curWeekDay to weekday of (current date) as integer

        set n to (12 - curWeekDay) mod 7 -- Number of days until Thursday

        if n = 0 then set n to 1 -- Thursday is the exception -> Friday

        set remindMeDate to (current date) + n * days

else if reminderDate = "1 Week" then

        set remindMeDate to (current date) + 7 * days

else if reminderDate = "1 Month" then

        set remindMeDate to (current date)

        tell remindMeDate to set its month to (its month as integer) + 1

else if reminderDate = "3 Months" then

        set remindMeDate to (current date)

        tell remindMeDate to set its month to (its month as integer) + 3

end if

 

set time of remindMeDate to 9 * hours -- 9a.m. on day of reminding

 

tell application "Mail"

        # Flag selected email/message in Mail

        set theMessage's flag index to FlagIndex

        

        # Get the unique identifier (ID) of selected email/message

        set theOrigMessageId to theMessage's message id

end tell

#we need to encode % with %25 because otherwise the URL will be screwed up in

#Reminders and you won't be able to just click on it to open the linked message

#in Mail

 

set theUrl to the contents of ["message:%3C", ¬

        replaceText(theOrigMessageId, "%", "%25"), ¬

        "%3E"] as text

 

# determine correct Reminder's list based on account of email/message

tell application "Mail" to tell the account of theMessage's mailbox to ¬

        if its name = WorkAccountName then

                set RemindersList to WorkRemindersList

        else if its name = PersonalAccountName then

                set RemindersList to PersonalRemindersList

        else

                #default list name in Reminders

                set RemindersList to "Reminders"

        end if

 

# create new reminder with proper due date, subject name and the URL

# linking to the email in Mail

tell application "Reminders" to tell list RemindersList to ¬

        make new reminder with properties {name:theSubject ¬

                , remind me date:remindMeDate, body:theUrl}

 

display notification "Reminder set" with title ¬

        theSubject subtitle remindMeDate as text

 

# string replace function

# used to replace % with %25

on replaceText(subject, find, replace)

        set text item delimiters to {replace, find}

        subject's text items as text

end replaceText

 

 

This version of the script also leaves Reminders in the background, without bringing it into focus, as there's no need.  This way, it doesn't pull your attention away from your emails when you're sifting through messages and triggering the script.  

 

 

Edited by CJK
Because Alfred's forum makes formatting posts extremely, extremely irritating.
Link to comment

Hi CJK,

 

Thanks for taking the time to review and optimize the script, appreciate it! ?

The delay still persists though. It's weird because I have other (albeit slightly smaller) scripts that I run with Alfred and they run without delay.

When I run your script with the Script Editor, it runs instantaneously but as soon as I run it with Alfred (or turn it into an application) there's a delay of (I think exactly) 5 seconds each time.

 

Some screenshots:

 

 

 

 

Schermafbeelding 2018-10-31 om 09.17.07.png

Schermafbeelding 2018-10-31 om 09.17.27.png

Edited by squandre
Link to comment

So your workflow is set up exactly the same as mine, and now using exactly the same script.  Yet yours presents with a 5-second delay in _Alfred_, and mine does not.  This might suggest that it's something specific to your system that is creating the delay.  You could try debugging the workflow.  Mine didn't reveal anything interesting, so if yours does, that might be a clue.

 

Otherwise, see if anyone who knows more than I chimes in with some suggestions or ideas.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...