From 8eb6f343e66a8853b7377092aaa06eea49716d37 Mon Sep 17 00:00:00 2001 From: "Brenton M. Wiernik" Date: Mon, 9 Dec 2019 12:45:47 -0500 Subject: [PATCH] Support Windows Store version of QuickLook --- README.md | 4 +- chrome/content/Bridge.cs | 49 +++++++++++++++++++++ chrome/content/Bridge.exe | Bin 0 -> 5120 bytes chrome/content/zoteroquicklook.js | 68 ++++++++++++++++++++---------- 4 files changed, 95 insertions(+), 26 deletions(-) create mode 100644 chrome/content/Bridge.cs create mode 100644 chrome/content/Bridge.exe diff --git a/README.md b/README.md index ab85a75..9caf3c4 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,7 @@ If you do not like Gloobus, you can define a custom QuickLook command: ## Installing on Windows -On Windows, you must first install a QuickLook tool. By default, ZoteroQuickLook is set up to work with [QuickLook](https://github.com/QL-Win/QuickLook/releases). - -Note that you must install QuickLook using the `.msi` installer, not by installing through the Windows Store. The Windows Store version of QuickLook does not provide a way for other programs to integrate with it. You can use the `.zip` version of QuickLook, but you must follow the steps below to set up a custom view command. +On Windows, you must first install a QuickLook tool. By default, ZoteroQuickLook is set up to work with [QuickLook](https://github.com/QL-Win/QuickLook/releases). Note that you must install QuickLook using either the `.msi` installer or through the Windows Store. If you use the `.zip` version of QuickLook, you must also set up a custom view command. Alternative QuickLook tools for Windows include [Seer](http://1218.io), [WinQuickLook](https://github.com/shibayan/WinQuickLook), and the paid software [MaComfort](https://leonardo.re/macomfort/). In my experience, the default option, QuickLook, is the most stable and powerful and least resource intensive option. You can choose another QuickLook program if you like. The software must be able to take a file name as a command line parameter. diff --git a/chrome/content/Bridge.cs b/chrome/content/Bridge.cs new file mode 100644 index 0000000..694f21e --- /dev/null +++ b/chrome/content/Bridge.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; +using System.IO.Pipes; +using System.Security.Principal; +using System.Windows.Forms; + +namespace Bridge +{ + internal static class Program + { + private static void Main(string[] args) + { + if (args.Length != 1) + { + MessageBox.Show("Usage: Bridge.exe \"\""); + return; + } + + SendMessage(Toggle, args[0]); + } + + private static readonly string PipeName = "QuickLook.App.Pipe." + WindowsIdentity.GetCurrent().User?.Value; + private const string Toggle = "QuickLook.App.PipeMessages.Toggle"; + + private static void SendMessage(string pipeMessage, string path = null) + { + if (path == null) + path = ""; + + try + { + using (var client = new NamedPipeClientStream(".", PipeName, PipeDirection.Out)) + { + client.Connect(1000); + + using (var writer = new StreamWriter(client)) + { + writer.WriteLine($"{pipeMessage}|{path}"); + writer.Flush(); + } + } + } + catch (Exception e) + { + MessageBox.Show("QuickLook not found. Please install QuickLook (http://pooi.moe/QuickLook/) or specify a custom view command instead."); + } + } + } +} \ No newline at end of file diff --git a/chrome/content/Bridge.exe b/chrome/content/Bridge.exe new file mode 100644 index 0000000000000000000000000000000000000000..e0de08ebd588b8d3785cd3b0efe162fedc6d7430 GIT binary patch literal 5120 zcmeHKU2I%O6+UxquboZ3vE3w1T0(EuNpaoy+9n}QQaf4ycc~pa-nAnlOUd24v*eD8B|0oB$V>NPbum{iFiN)9zYZ-REdW^5ebR3NC-uFs1O37KJZqFhHvKH zUE4_&%xl%L=ggUN&YU^t+?g|HXD(c)CL(G^zk8SHEsUyVG<+~v2RrrnZ&UQk9XAiY z#inl_%&)l8tcai_?6T?Dz8{2Uft#Z0o33w;&*sc>P~=v7d-71MdTxSfnl(}4{p1hp zyWOEQ?PLQ)Nl@A%YVVU6P4o=90wx9{vKyGTUyZbm4!UXvWxhewq5n6=cp8b&`#nUn z3eOPTQbD-4T_So2v}wqlxR>{!x!EvXOSNJC>?V0D;$}>Y(0`_4d8t8ueXzl zBZ)+ew+HQ@MTXoaY|ii<4YKIbXLZDZe~wP%Bb;a_EnK2@C}*#UpJ1b&6jlej01o#x zKe79%mH?+I+0zNIt_=-^2ewifaL+u(Tji$o#D>k7|> z!u3m1Ni-uyf5h0mkfU3`p`W^^7P8|QKft^P+jNh5K>>5su$-MgV30aC^btEsdvzS? z;fSaB`aUCY1T*zq9c!r3UD1jD6I-01U(w%Kg5J~cW%?7_MG2@#(CgF&`lR8rB+aos zMuL6@EI}_bpQT6`y+(=_0F(5*=3dm?L*ORpZH=ELg@4sJ4)`6W-~l?W%!v0^QCnvn zw9KYxKX68aWMkiR>lXm$OeOg$RoNThgz>DOZos2`2Q_csAJ|Xzy=Qb-g@vA>jt+wc z*$#S_F?jzj_S_Gcq$dG8=p2=eJ#-Ry8gRy7Gy=SruF@G}fNFFZ(XY`{SoJlekp%2X zv#045Dj3fI-e4K}0sWhv*76gSLTbw6inY`CaGrM3&jBAs{

Z`ZHiR-2v9Tu58`h zrZCx@Xr80pn!S~#a>KoHz3SttHZ&6ys~$g1xta`l*~-pRSvrC6+yZ5b+z;KbHqV#2 z;J(8t$Nl0Am(nhAs<;(i$47-*1Svc2%1R*Zg2yQzlu8)pAa&L*b2=~FkWaflltep? z1%gww03$C{OC_~%B*cj>R6}U6MTv)#$p8FWAg*jM#)5Li_3Y3M{CV!#YZ{Xq{P`-( zE^{RYR>Ae)!v+^RFD}|%l~ZK3#n&1(#Vf5vE+n+$X2Fl>iqWK3l`8~|D|HWY+^NE= znl*c>o<$MXw>4XH$&PLYX6MvzNIJ-0wxLpSlJ4^ahDA+2B*&@!Nn zz6@Cp68*peU`619PD7r?&QTRyhpx~xcmYNWcea8*i{`+oKz0UQHujg`Eb@4GU7Z)Lj$JCUs?7$N;VF*Uv94?mu?tmC@}O^I+F> z!Y~rb5_SO4fC)(Ntc}G*)8|!E%^Q2q3%hbQ@EgZ9zanrNlw6chrWieHot?-xZtaoy zDh;dG3@TE)8!UDAJ-eo^Oov)yHaO-nbrxP=AK@8~-ko`jFX6p?N!4+intJ0lxB1+7 z?)5isRvx*!EBl-5jpt5Yc=ewQ0%NC^)D4nLb9S*ts=hs=TAx zAyTXI;M$-{;UfYhU_9_1uWXIWdM0@qZ1uR1;P*^ADWb`58Lsw0hU!3{KT9LGWBSi zrXf?(E5_h$1yzvB;3a%HRfm}9r?vjsnC`~<>%Obq9=y*n?av(62gvYMGouMa>$mFmkVCagbH5{r>nw0C7l&swq;-0 zbwnV8<*?5Q%BO5uwpItzX4&@LWiG>d8rAzjnQ1nZ)!)x8HsPlO?DCOYhto5)kxIpL z@lvDIuvEuJzq@gb=X_RrB6HuMewUt*oo>#xT~(mOI&VK>(RPa z6Kz8e(x+2Z7Ekk4?wOu~!)aS){ng+K7iqKVjyR}Z5XNQOlRS1xE9w6PYwD)=Z?S!- lzYzoo4E5K)(CPXY|7_fL1kC7n>k<8Xb=#{x6a17!;J*%63CI8d literal 0 HcmV?d00001 diff --git a/chrome/content/zoteroquicklook.js b/chrome/content/zoteroquicklook.js index bfdf057..58bec48 100644 --- a/chrome/content/zoteroquicklook.js +++ b/chrome/content/zoteroquicklook.js @@ -14,7 +14,7 @@ Zotero.ZoteroQuickLook = { document.getElementById('zotero-items-tree').addEventListener("keydown",this.onKey,false); if (!this.initialized) { - Zotero.debug("ZoterQuickLook: starts init",3); + Zotero.debug("ZoteroQuickLook: starts init",3); //Trim the preference to avoid problems of extra spaces this.customviewcommand = this.getPref('customviewcommand').replace(/^\s+|\s+$/g, ''); @@ -32,8 +32,8 @@ Zotero.ZoteroQuickLook = { } } - // Get the path of the embedded Perl script (Mac/Linux) and word processor plugins scripts (Mac) - if (!Zotero.isWin && this.customviewcommand == "") { + // Get the path of the embedded Perl script (Mac/Linux) or QuickLook bridge executable (Win) + if (this.customviewcommand == "") { await new Promise(function (resolve) { var MY_ID = "zoteroquicklook@gmail.com"; Components.utils.import("resource://gre/modules/AddonManager.jsm"); @@ -43,8 +43,7 @@ Zotero.ZoteroQuickLook = { resolve(); }.bind(this)); }.bind(this)); - } - else { + } else { this.initExecutable(); } @@ -62,8 +61,15 @@ Zotero.ZoteroQuickLook = { * Initializes external scripts */ initScripts: async function (scriptURL) { - let path = await this.copyURLToTempDir(scriptURL + "/zoteroquicklook.pl"); - Zotero.ZoteroQuickLook.initExecutable(path); + if (!Zotero.isWin) { + let path = await this.copyURLToTempDir(scriptURL + "/zoteroquicklook.pl"); + Zotero.debug("ZoteroQuickLook: Copying zoteroquicklook.pl file to: " + path); + Zotero.ZoteroQuickLook.initExecutable(path); + } else { + let path = await this.copyURLToTempDir(scriptURL + "/Bridge.exe"); + Zotero.debug("ZoteroQuickLook: Copying Bridge.exe file to: " + path); + Zotero.ZoteroQuickLook.initExecutable(path); + } /* // Check if the word processor integration for Zotero is installed and install the quicklook word processor script @@ -116,6 +122,7 @@ Zotero.ZoteroQuickLook = { */ }, + /* initIntegration: function(){ Zotero.Integration.Interface.prototype.quickLook = function() { @@ -166,8 +173,11 @@ Zotero.ZoteroQuickLook = { } } }, + */ initExecutable: function(scriptLocation) { + Zotero.debug("ZoteroQuickLook: Script location is " + scriptLocation, 3); + //Initialize the command that is used. //TODO: The script fails when custom view command is bogus. @@ -221,13 +231,28 @@ Zotero.ZoteroQuickLook = { } - else if(Zotero.isWin){ + else if(Zotero.isWin){ + /* TODO: Checking for existence of Windows Store Apps isn't working + // Check if QuickLook is installed. localappdata = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties).get("LocalAppData", Components.interfaces.nsIFile).path; - this.viewerExecutable = Zotero.File.pathToFile(localappdata + "\\Programs\\QuickLook\\QuickLook.exe"); - if(this.viewerExecutable.exists() === false){ + qlMsiLocation = Zotero.File.pathToFile(localappdata + "\\Programs\\QuickLook\\QuickLook.exe"); + winApps = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile).initWithPath("C:\\Program Files\\WindowsApps\\").directoryEntries; + winAppsArray = []; + while(winApps.hasMoreElements()) { + var entry = winApps.getNext(); + entry.QueryInterface(Components.interfaces.nsIFile); + winAppsArray.push(entry); + } + qlPublisher = /PaddyXu\.QuickLook/g ; + qlWinStoreInstalled = winAppsArray.some(e => qlPublisher.test(e)); + if(qlMsiLocation.exists() === false && qlWinStoreInstalled === false){ alert("QuickLook not found. Please install QuickLook (http://pooi.moe/QuickLook/) or specify a custom view command instead."); + return; } - this.viewerBaseArguments=['']; + */ + + this.viewerExecutable = Zotero.File.pathToFile(scriptLocation); + this.viewerBaseArguments=['']; } }, @@ -256,7 +281,7 @@ Zotero.ZoteroQuickLook = { }, closeQuickLook: function(){ - Zotero.debug("ZoterQuickLook: is killing quicklook viewer."); + Zotero.debug("ZoteroQuickLook: is killing quicklook viewer."); Zotero.ZoteroQuickLook.proc.kill(); Zotero.ZoteroQuickLook.proc=null; }, @@ -329,7 +354,7 @@ Checks the attachment file or writes a content of a note to a file and then push let iCloudPath = Zotero.File.getEvictedICloudPath(path); if (await OS.File.exists(iCloudPath)) { // Launching qlmanage should trigger an iCloud download - Zotero.debug("ZoterQuickLook: Triggering download of iCloud file"); + Zotero.debug("ZoteroQuickLook: Triggering download of iCloud file"); await args.push(Zotero.ZoteroQuickLook.cleanFileName(path)); return; } @@ -422,7 +447,7 @@ Checks the attachment file or writes a content of a note to a file and then push openQuickLook: async function(items) { - Zotero.debug("ZoterQuickLook: opening viewer",3); + Zotero.debug("ZoteroQuickLook: opening viewer",3); var args=this.viewerBaseArguments.slice(); @@ -474,7 +499,7 @@ Checks the attachment file or writes a content of a note to a file and then push ///If no files are specified, exit. if (! filesFound ) { - Zotero.debug("ZoterQuickLook: thinks that no files are selected",3); + Zotero.debug("ZoteroQuickLook: thinks that no files are selected",3); return false; } @@ -495,20 +520,17 @@ Checks the attachment file or writes a content of a note to a file and then push // If no file arguments were added to the base arguments, exit. if (argsString == baseArgsString) { - Zotero.debug("ZoterQuickLook: Only linked URLs are selected",3); + Zotero.debug("ZoteroQuickLook: Only linked URLs are selected",3); return false; } //Write to debug what is called - Zotero.debug("ZoterQuickLook: calling a shell command: " +this.viewerExecutable.path +argsString,3); - + Zotero.debug("ZoteroQuickLook: calling a shell command: " +this.viewerExecutable.path +argsString,3); + Zotero.ZoteroQuickLook.proc = Components.classes["@mozilla.org/process/util;1"]. createInstance(Components.interfaces.nsIProcess); - Zotero.ZoteroQuickLook.proc.init(Zotero.ZoteroQuickLook.viewerExecutable); - Zotero.ZoteroQuickLook.proc.runw(false, args, args.length); - return true; }, @@ -546,12 +568,12 @@ Checks the attachment file or writes a content of a note to a file and then push } // 38 is arrow up and 40 is arrow down. If quick look is active, we will close it and open it again with the new selection. else if((event.keyCode==38 || event.keyCode==40)&& !(event.ctrlKey || event.altKey || event.metaKey) && (Zotero.ZoteroQuickLook.isActive() || Zotero.ZoteroQuickLook.isBrowseMode)) { - Zotero.debug("ZoterQuickLook: is browsing"); + Zotero.debug("ZoteroQuickLook: is browsing"); if (! Zotero.ZoteroQuickLook.isBrowseMode) Zotero.ZoteroQuickLook.closeQuickLook(); success=Zotero.ZoteroQuickLook.openQuickLook(items); // If the items were not found, the viewer stays closed. However, if we are browsing through a list of items, we want to reopen the viewer when we hit the next item that has an attachment. Zotero.ZoteroQuickLook.isBrowseMode = ! success; - Zotero.debug("ZoterQuickLook: has browse mode set to " + Zotero.ZoteroQuickLook.isBrowseMode,3); + Zotero.debug("ZoteroQuickLook: has browse mode set to " + Zotero.ZoteroQuickLook.isBrowseMode,3); } return;