Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catalina support #95

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 79 additions & 4 deletions quotefix/fixer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from quotefix.utils import swizzle
from quotefix.attribution import CustomizedAttribution
from quotefix.messagetypes import *
from objc import Category, lookUpClass
from objc import Category, lookUpClass, registerMetaDataForSelector
from logger import logger
import re, traceback, objc

Expand Down Expand Up @@ -42,7 +42,43 @@ def sendEvent(self, original, event):
)
original(self, event)

def fix(self):
def call_fix_later(self):
"""Tell the ComposeBackEnd to call fix() later, when the message is ready.

This became necessary starting around Catalina, when you could no
longer ask the ComposeBackEnd to immediately give you the message
instance.

"""
try:
logger.debug("entered fix_future")
backend = self.backEnd()
future = backend.messageFuture()
future.addSuccessBlock_(lambda message: fix(self, message))
logger.debug("success block added")
except Exception:
logger.critical(traceback.format_exc())
if self.app.is_debugging:
NSRunAlertPanel(
'QuoteFix caught an exception',
'The QuoteFix plug-in caught an exception in call_fix_later:\n\n' +
traceback.format_exc() +
'\nPlease contact the developer quoting the contents of this alert.',
None, None, None
)

def fix(self, message=None):
"""Run all of the relevant fixes on a new message.

This function is attached as a method on DocumentEditor and/or
ComposeViewController.

If message is None then we get the message from the
ComposeBackEnd. Doing this became impossible around Catalina,
where instead we ask the ComposeBackEnd to call this function
later with the message: see call_fix_later elsewhere in this file.

"""
try:
# if toggle key is active, temporarily switch the active state
is_active = self.app.toggle_key_active ^ self.app.is_active
Expand Down Expand Up @@ -82,12 +118,18 @@ def fix(self):

if attributor:
try:
if message is None:
# Must be pre-Catalina, where we can get the
# message directly without having to go through
# the future.
assert not HAS_MESSAGE_FUTURE
message = backend.message()
for original in objc.getInstanceVariable(backend, '_originalMessages'):
attributor(
app = self.app,
editor = self,
dom = htmldom,
reply = backend.message(),
reply = message,
inreplyto = original,
)
backend.setHasChanges_(False)
Expand Down Expand Up @@ -384,7 +426,40 @@ def show(self, original):
elif not self.move_above_new_signature(htmldom, view):
view.moveToEndOfDocument_(self)

ComposeViewController.fix = fix
# As of Catalina, you can't get the message directly from the
# backend. Rather, you have to get the EFFuture instance (see
# private EmailFoundation.framework), and tell it to call you when
# the message is ready.)
ComposeBackEnd = lookUpClass("ComposeBackEnd")
HAS_MESSAGE_FUTURE = bool(
ComposeBackEnd.instancesRespondToSelector_("messageFuture")
)

if HAS_MESSAGE_FUTURE:
# Must tell PyObjC that [EFFuture addSuccessBlock:] takes a
# block that itself takes an object, which is presumably the
# result of the future.
registerMetaDataForSelector(
b"EFFuture",
b"addSuccessBlock:",
dict(
arguments={
2: {
"callable": {
"retval": {"type": b"v"},
"arguments": {
"0": {"type": b"^v"},
"1": {"type": b"@"},
},
},
},
},
),
)
ComposeViewController.fix = call_fix_later
else:
ComposeViewController.fix = fix

ComposeViewController.remove_attachment_placeholders = remove_attachment_placeholders
ComposeViewController.remove_quotes = remove_quotes
ComposeViewController.make_selectable_quotes = make_selectable_quotes
Expand Down
4 changes: 4 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@
# Mail 11.0 (3445.1.3) High Sierra beta
'C86CD990-4660-4E36-8CDA-7454DEB2E199'
],
'Supported10.15PluginCompatibilityUUIDs': [
# Version 13.4 (3608.80.23.2.2) Catalina 10.15.5
'6EEA38FB-1A0B-469B-BB35-4C2E0EEA9053',
],
# settings for Sparkle
'SUFeedURL' : 'https://raw.github.com/robertklep/quotefixformac/master/updates/appcast.xml',
'SUEnableAutomaticChecks' : False,
Expand Down