diff --git a/safari/Universal/Kagi Search (macOS)/Base.lproj/Main.storyboard b/safari/Universal/Kagi Search (macOS)/Base.lproj/Main.storyboard index ee58e6b..3357704 100644 --- a/safari/Universal/Kagi Search (macOS)/Base.lproj/Main.storyboard +++ b/safari/Universal/Kagi Search (macOS)/Base.lproj/Main.storyboard @@ -306,9 +306,9 @@ - + - + @@ -326,11 +326,11 @@ - + - + diff --git a/safari/Universal/Kagi-Search-macOS-Info.plist b/safari/Universal/Kagi Search (macOS)/Kagi-Search-macOS-Info.plist similarity index 100% rename from safari/Universal/Kagi-Search-macOS-Info.plist rename to safari/Universal/Kagi Search (macOS)/Kagi-Search-macOS-Info.plist diff --git a/safari/Universal/Kagi Search.xcodeproj/project.pbxproj b/safari/Universal/Kagi Search.xcodeproj/project.pbxproj index 11116d8..7aec629 100644 --- a/safari/Universal/Kagi Search.xcodeproj/project.pbxproj +++ b/safari/Universal/Kagi Search.xcodeproj/project.pbxproj @@ -10,8 +10,8 @@ 3E1A51362B1734B70010A4C4 /* Kagi Search Extension iOS.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 3ED5D48F2B0DE087009DDDAD /* Kagi Search Extension iOS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 3E1A513B2B180B890010A4C4 /* UpgradeChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E1A513A2B180B890010A4C4 /* UpgradeChecker.swift */; }; 3E1A513C2B180CBE0010A4C4 /* UpgradeChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E1A513A2B180B890010A4C4 /* UpgradeChecker.swift */; }; + 3E7B281A2B86D220005EB620 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 3E7B28192B86D220005EB620 /* manifest.json */; }; 3E9DF5082B3E3E70005DF2C3 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 3ED5D55B2B0DE720009DDDAD /* manifest.json */; }; - 3E9DF5092B3E3E71005DF2C3 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 3ED5D55B2B0DE720009DDDAD /* manifest.json */; }; 3EB8FA422B61F6740052E8D4 /* Deeplinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EB8FA412B61F6740052E8D4 /* Deeplinks.swift */; }; 3EB8FA432B61F6740052E8D4 /* Deeplinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EB8FA412B61F6740052E8D4 /* Deeplinks.swift */; }; 3EB8FA472B6231DC0052E8D4 /* Settings_Animation_dark.gif in Resources */ = {isa = PBXBuildFile; fileRef = 3EB8FA452B6231DB0052E8D4 /* Settings_Animation_dark.gif */; }; @@ -133,6 +133,7 @@ /* Begin PBXFileReference section */ 3E1A513A2B180B890010A4C4 /* UpgradeChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpgradeChecker.swift; sourceTree = ""; }; + 3E7B28192B86D220005EB620 /* manifest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = manifest.json; sourceTree = ""; }; 3EB8FA412B61F6740052E8D4 /* Deeplinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Deeplinks.swift; sourceTree = ""; }; 3EB8FA452B6231DB0052E8D4 /* Settings_Animation_dark.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = Settings_Animation_dark.gif; sourceTree = ""; }; 3EB8FA462B6231DB0052E8D4 /* Settings_Animation_light.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = Settings_Animation_light.gif; sourceTree = ""; }; @@ -141,7 +142,7 @@ 3EC41D232B21B587009B17FE /* macOS Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "macOS Assets.xcassets"; sourceTree = ""; }; 3EC772502B2C48CE00E40354 /* Kagi Search iOS copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Kagi Search iOS copy-Info.plist"; path = "/Users/nano/Kagi/kagi-for-safari-macos/Kagi Search iOS copy-Info.plist"; sourceTree = ""; }; 3EC772622B2C492F00E40354 /* Kagi Search Extension iOS copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Kagi Search Extension iOS copy-Info.plist"; path = "/Users/nano/Kagi/kagi-for-safari-macos/Kagi Search Extension iOS copy-Info.plist"; sourceTree = ""; }; - 3EC772662B2F904200E40354 /* Kagi-Search-macOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Kagi-Search-macOS-Info.plist"; sourceTree = ""; }; + 3EC772662B2F904200E40354 /* Kagi-Search-macOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Kagi-Search-macOS-Info.plist"; sourceTree = ""; }; 3ED5D48F2B0DE087009DDDAD /* Kagi Search Extension iOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Kagi Search Extension iOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 3ED5D4AC2B0DE2BD009DDDAD /* Kagi Search Extension macOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Kagi Search Extension macOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 3ED5D4C92B0DE324009DDDAD /* Kagi Search Extension (iOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Kagi Search Extension (iOS).entitlements"; sourceTree = ""; }; @@ -297,6 +298,7 @@ 3ED5D4FE2B0DE6A5009DDDAD /* Kagi Search (macOS) */ = { isa = PBXGroup; children = ( + 3EC772662B2F904200E40354 /* Kagi-Search-macOS-Info.plist */, 3ED5D4FF2B0DE6A5009DDDAD /* NSWindow+Helpers.swift */, 3ED5D5002B0DE6A5009DDDAD /* Main.storyboard */, 3ED5D5022B0DE6A5009DDDAD /* AppDelegate.swift */, @@ -341,7 +343,6 @@ 3ED5D5552B0DE720009DDDAD /* popup.js */, 3ED5D5562B0DE720009DDDAD /* background.js */, 3ED5D55A2B0DE720009DDDAD /* popup.html */, - 3ED5D55B2B0DE720009DDDAD /* manifest.json */, 3ED5D55C2B0DE720009DDDAD /* popup.css */, ); path = Resources; @@ -350,6 +351,7 @@ 3ED5D5772B0DE75F009DDDAD /* iOS (Extension) */ = { isa = PBXGroup; children = ( + 3ED5D55B2B0DE720009DDDAD /* manifest.json */, 3ED5D4C92B0DE324009DDDAD /* Kagi Search Extension (iOS).entitlements */, 3ED5D5782B0DE75F009DDDAD /* Info.plist */, ); @@ -359,6 +361,7 @@ 3ED5D5792B0DE75F009DDDAD /* macOS (Extension) */ = { isa = PBXGroup; children = ( + 3E7B28192B86D220005EB620 /* manifest.json */, 3ED5D57A2B0DE75F009DDDAD /* Kagi Search Extension (macOS).entitlements */, 3ED5D57B2B0DE75F009DDDAD /* Info.plist */, 3E1A513A2B180B890010A4C4 /* UpgradeChecker.swift */, @@ -369,7 +372,6 @@ C31E69142823DD4E00B1491B = { isa = PBXGroup; children = ( - 3EC772662B2F904200E40354 /* Kagi-Search-macOS-Info.plist */, C39A9F7028588C0100E4C0A3 /* MainConfig.xcconfig */, 3ED5D5772B0DE75F009DDDAD /* iOS (Extension) */, 3ED5D5792B0DE75F009DDDAD /* macOS (Extension) */, @@ -599,9 +601,9 @@ buildActionMask = 2147483647; files = ( 3ED5D5722B0DE720009DDDAD /* popup.css in Resources */, - 3E9DF5092B3E3E71005DF2C3 /* manifest.json in Resources */, 3ED5D58F2B0DFC34009DDDAD /* _locales in Resources */, 3ED5D56E2B0DE720009DDDAD /* popup.html in Resources */, + 3E7B281A2B86D220005EB620 /* manifest.json in Resources */, 3ED5D5682B0DE720009DDDAD /* background.js in Resources */, 3ED5D5922B0DFC81009DDDAD /* images in Resources */, 3ED5D5662B0DE720009DDDAD /* popup.js in Resources */, @@ -1277,7 +1279,7 @@ "DEVELOPMENT_TEAM[sdk=macosx*]" = TFVG979488; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "Kagi-Search-macOS-Info.plist"; + INFOPLIST_FILE = "Kagi Search (macOS)/Kagi-Search-macOS-Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = ""; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_NSHumanReadableCopyright = "Kagi Search is a quick, user-centric, 100% privacy-respecting search engine with results augmented by non-commercial indexes and personalized searches."; @@ -1320,7 +1322,7 @@ "DEVELOPMENT_TEAM[sdk=macosx*]" = TFVG979488; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "Kagi-Search-macOS-Info.plist"; + INFOPLIST_FILE = "Kagi Search (macOS)/Kagi-Search-macOS-Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = ""; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_NSHumanReadableCopyright = "Kagi Search is a quick, user-centric, 100% privacy-respecting search engine with results augmented by non-commercial indexes and personalized searches."; diff --git a/safari/Universal/MainConfig.xcconfig b/safari/Universal/MainConfig.xcconfig index 3f70e1c..9c8b7de 100644 --- a/safari/Universal/MainConfig.xcconfig +++ b/safari/Universal/MainConfig.xcconfig @@ -1,3 +1,3 @@ -MARKETING_VERSION = 2.2.1 -CURRENT_PROJECT_VERSION = 22 // this needs to be increased with each version change as well (not set to 1 when version is updated) +MARKETING_VERSION = 2.2.2 +CURRENT_PROJECT_VERSION = 24 // this needs to be increased with each version change as well (not set to 1 when version is updated) PRODUCT_NAME = Kagi for Safari diff --git a/safari/Universal/Shared (App)/Base.lproj/Main.html b/safari/Universal/Shared (App)/Base.lproj/Main.html index 656eae4..5ca48a2 100644 --- a/safari/Universal/Shared (App)/Base.lproj/Main.html +++ b/safari/Universal/Shared (App)/Base.lproj/Main.html @@ -32,6 +32,9 @@

Instructions

    +
  1. +

    Optional: Select the search engine you want to redirect to Kagi in the extension popup.

    +
  2. To enable Kagi in Private Browsing, check the "Allow in Private Browsing" checkboxenable the "Private Browsing" toggle switch. Then copy your Kagi private session link from your Kagi account settings into the extension popup. diff --git a/safari/Universal/Shared (Extension)/Resources/background.js b/safari/Universal/Shared (Extension)/Resources/background.js index 7e6a3b1..b6e373e 100644 --- a/safari/Universal/Shared (Extension)/Resources/background.js +++ b/safari/Universal/Shared (Extension)/Resources/background.js @@ -278,6 +278,27 @@ const yahooUrls = { "search.yahoo.com": "p" }; const builtInEngines = Object.assign({}, googleUrls, yandexUrls, ddgUrls, bingUrls, baiduUrls, sogouUrls, ecosiaUrls, yahooUrls); +const domainMap = { + "Google": ["google.com.au", "google.md", "google.ru", "google.me", "google.com.qa", "google.com.gt", "google.se", "google.tm", "google.vg", "google.it", "google.cat", "google.com.ru", "google.com.gr", "google.ee", "google.cd", "google.sk", "google.com.ly", "google.hn", "google.co.jp", "google.ad", "google.com.sg", "google.ie", "google.co.vi", "google.kg", "google.com.kh", "google.co.ck", "google.is", "google.tt", "google.vu", "google.bg", "google.ch", "google.com.sa", "google.tn", "google.pl", "google.ro", "google.gm", "google.tl", "google.mg", "google.dk", "google.com.bo", "google.je", "google.com.kw", "google.dz", "google.ga", "google.com.gh", "google.lt", "google.com.ag", "google.ps", "google.com.vc", "google.com.pr", "google.co.cr", "google.pn", "google.com.tr", "google.sn", "google.tg", "google.gg", "google.gr", "google.com.mt", "google.nu", "google.cm", "google.lk", "google.co.mz", "google.cv", "google.sm", "google.no", "google.al", "google.bi", "google.com.af", "google.sr", "google.jo", "google.sh", "google.co.uk", "google.co.bw", "google.dm", "google.at", "google.co.ug", "google.dj", "google.si", "google.com.pg", "google.com.tj", "google.co.za", "google.nl", "google.sc", "google.ae", "google.mv", "google.ne", "google.gy", "google.com.sl", "google.co.in", "google.com.bn", "google.ht", "google.com.ua", "google.com.my", "google.co.kr", "google.com", "google.by", "google.com.cu", "google.com.lb", "google.co.nz", "google.mu", "google.com.om", "google.as", "google.com.pe", "google.mk", "google.td", "google.es", "google.az", "google.com.hk", "google.com.do", "google.bt", "google.am", "google.fm", "google.com.mx", "google.fi", "google.com.bz", "google.st", "google.com.vn", "google.rs", "google.bs", "google.cn", "google.com.pa", "google.com.sb", "google.lv", "google.co.uz", "google.co.hu", "google.co.ve", "google.co.zw", "google.com.ai", "google.com.co", "google.ci", "google.com.uy", "google.cl", "google.mw", "google.cz", "google.co.il", "google.co.th", "google.be", "google.hr", "google.fr", "google.im", "google.com.ec", "google.cg", "google.iq", "google.com.np", "google.gl", "google.co.ke", "google.co.id", "google.ml", "google.ms", "google.com.ni", "google.mn", "google.ki", "google.lu", "google.hu", "google.rw", "google.co.ma", "google.com.tw", "google.co.ls", "google.com.et", "google.li", "google.com.br", "google.bj", "google.com.py", "google.co.tz", "google.ba", "google.co.ao", "google.bf", "google.com.ph", "google.com.sv", "google.com.bd", "google.com.mm", "google.la", "google.ws", "google.com.fj", "google.co.zm", "google.cf", "google.nr", "google.to", "google.com.jm", "google.com.ar", "google.com.gi", "google.ca", "google.kz", "google.com.cy", "google.de", "google.com.na", "google.com.pk", "google.pt", "google.ge", "google.so", "google.com.bh", "google.com.eg", "google.com.ng"], + "DuckDuckGo": ["duckduckgo.com", "duckduckgo.pl", "duckduckgo.jp", "duckduckgo.co", "duckduckco.de", "duckduckgo.ca", "duckduckgo.co.uk", "duckduckgo.com.mx", "duckduckgo.com.tw", "duckduckgo.dk", "duckduckgo.in", "duckduckgo.ke", "duckduckgo.mx", "duckduckgo.nl", "duckduckgo.org", "duckduckgo.sg", "duckduckgo.uk", "duckgo.com", "ddg.co", "ddg.gg", "duck.co", "duck.com"], + "Yahoo": ["search.yahoo.com"], + "Ecosia": ["ecosia.org"], + "Bing": ["bing.com"], + "Sogou": ["m.so.com", "so.com", "sogou.com", "m.sogou.com"], + "Baidu": ["baidu.com", "m.baidu.com"], + "Yandex": ["yandex.ru", "yandex.org", "yandex.net", "yandex.net.ru", "yandex.com.ru", "yandex.ua", "yandex.com.ua", "yandex.by", "yandex.eu", "yandex.ee", "yandex.lt", "yandex.lv", "yandex.md", "yandex.uz", "yandex.mx", "yandex.do", "yandex.tm", "yandex.de", "yandex.ie", "yandex.in", "yandex.qa", "yandex.so", "yandex.nu", "yandex.tj", "yandex.dk", "yandex.es", "yandex.pt", "yandex.pl", "yandex.lu", "yandex.it", "yandex.az", "yandex.ro", "yandex.rs", "yandex.sk", "yandex.no", "ya.ru", "yandex.com", "yandex.asia", "yandex.mobi"] +}; +function domainKeyForHost(knownHost) { + let domainKeys = Object.keys(domainMap); + for (let i=0; i -1) { + return domainKey; + } + } + return ""; +} +const supportedEngineNames = Object.keys(domainMap); const www = "www."; const yahoo = "search.yahoo.com"; const extensionId = "com.kagi.Kagi-Search-for-Safari.Extension (TFVG979488)"; @@ -288,10 +309,11 @@ var ua = {}, os = !0, rs = !0, currentEngine = "All", + defaultEngineToRedirect = "Google", defaultKagiSearchTemplate = "https://kagi.com/search?q=%s", kagiSearchTemplate = defaultKagiSearchTemplate, kagiPrivateSearchTemplate = "", - flagCheckedLocalStorageForPrivateSessionLink = false, + flagFetchedPreferences = false, customURLMode = 0, customURLList = [], regularTabIds = [], @@ -317,7 +339,8 @@ function captureQuery(a) { b.endsWith(yahoo) && (b = yahoo); const path = a.pathname; var shouldBlockGoogleNonSearch = (b in googleUrls && !(path.startsWith("/search"))); - if (b in builtInEngines && !(shouldBlockGoogleNonSearch) && (a = (new URLSearchParams(a.search)).get(builtInEngines[b]))) return a; + var shouldBlockRedirectBasedOnUserPreference = ([currentEngine, "All"].indexOf(domainKeyForHost(b)) < 0); + if (b in builtInEngines && !(shouldBlockGoogleNonSearch || shouldBlockRedirectBasedOnUserPreference) && (a = (new URLSearchParams(a.search)).get(builtInEngines[b]))) return a; } function rewriteQueryURL(a, b) { @@ -341,10 +364,10 @@ function rewriteQueryURL(a, b) { } var tk = 0; function checkForSearch(a) { - if (!flagCheckedLocalStorageForPrivateSessionLink) { - console.log("[checkForSearch] Search query started before local private session link was fetched"); - checkLocalStorageForPrivateSessionLink(function(){ - console.log("[checkForSearch] Fetched local private session link as part of first search query during current browsing session"); + if (!flagFetchedPreferences) { + console.log("[checkForSearch] Search query started before preferences were fetched"); + getPreferencesFromStorage(function(){ + console.log("[checkForSearch] Fetched preferences as part of first search query during current browsing session"); _checkForSearch(a); }); } else { @@ -414,13 +437,23 @@ function updatePrivateSessionLink(link) { } } -function checkLocalStorageForPrivateSessionLink(callback) { - browser.storage.local.get("kagiPrivateSessionLink", function(value) { +function getPreferencesFromStorage(callback) { + browser.storage.local.get(["kagiPrivateSessionLink","kagiEngineToRedirect"], function(value) { + // Private session link var link = value.kagiPrivateSessionLink; - if (typeof (link) !== "undefined") { + if (typeof (link) == "string") { updatePrivateSessionLink(link); } - flagCheckedLocalStorageForPrivateSessionLink = true; + // Engine to redirect + var engine = value.kagiEngineToRedirect; + if (typeof (engine) == "string") { + if (engine == "All" || supportedEngineNames.indexOf(engine) < 0) { + currentEngine = defaultEngineToRedirect; // default to redirecting Google + } else { + currentEngine = engine; + } + } + flagFetchedPreferences = true; callback(); }); } @@ -454,18 +487,21 @@ browser.runtime.onInstalled.addListener(function(details) { }); -// Check for a private session link at startup so that the first search +// Check for a private session link and default engine at startup so that the first search // in a private window or tab doesn't fail -checkLocalStorageForPrivateSessionLink(function(){ - console.log("Finished startup check for local private session link"); +getPreferencesFromStorage(function(){ + console.log("Finished fetching preferences on startup"); }); function messageReceived(data, sender) { let updatedKagiPrivateSessionLink = data["updatedKagiPrivateSessionLink"]; - if (stringIsValid(updatedKagiPrivateSessionLink)) { - return updatePrivateSessionLink(updatedKagiPrivateSessionLink) - .then(() => Promise.resolve(true)) - .catch((error) => Promise.reject(error)); + let updatedKagiEngineToRedirect = data["updatedKagiEngineToRedirect"]; + if (stringIsValid(updatedKagiPrivateSessionLink) || stringIsValid(updatedKagiEngineToRedirect)) { + // FIXME: Decide whether to send the session link and engine choice through storage or through the message itself. Right now we're doing both. + getPreferencesFromStorage(function(){ + console.log("Finished fetching preferences after receiving an update message from popup.js"); + }); + return Promise.resolve(true); } else { return false; } diff --git a/safari/Universal/Shared (Extension)/Resources/images/ToolbarItemIcon.pdf b/safari/Universal/Shared (Extension)/Resources/images/ToolbarItemIcon.pdf new file mode 100644 index 0000000..9ee31b9 Binary files /dev/null and b/safari/Universal/Shared (Extension)/Resources/images/ToolbarItemIcon.pdf differ diff --git a/safari/Universal/Shared (Extension)/Resources/images/ToolbarItemIcon.png b/safari/Universal/Shared (Extension)/Resources/images/ToolbarItemIcon.png index 7f6749d..f150bdd 100644 Binary files a/safari/Universal/Shared (Extension)/Resources/images/ToolbarItemIcon.png and b/safari/Universal/Shared (Extension)/Resources/images/ToolbarItemIcon.png differ diff --git a/safari/Universal/Shared (Extension)/Resources/popup.css b/safari/Universal/Shared (Extension)/Resources/popup.css index 4759cbd..61619d6 100644 --- a/safari/Universal/Shared (Extension)/Resources/popup.css +++ b/safari/Universal/Shared (Extension)/Resources/popup.css @@ -77,6 +77,10 @@ fieldset { input, select, p, label, button { width: 100%; } +fieldset input, fieldset select { + font-size: 0.9em; + font-weight: 300; +} fieldset select { margin-bottom: 8px; } @@ -85,8 +89,6 @@ fieldset input { border-style: solid; border-width: 1px; border-color: #eee; - font-size: 0.9em; - font-weight: 300; padding: 3px; } diff --git a/safari/Universal/Shared (Extension)/Resources/popup.html b/safari/Universal/Shared (Extension)/Resources/popup.html index a4b308a..5b40ae6 100644 --- a/safari/Universal/Shared (Extension)/Resources/popup.html +++ b/safari/Universal/Shared (Extension)/Resources/popup.html @@ -11,7 +11,7 @@
    • -

      Kagi searches enabled on:

      +

      Kagi extension enabled on:

      @@ -22,13 +22,29 @@

      Kagi searches enabled on:

    • +
    • +

      Engine to redirect

      +

      Select the search engine you want to redirect to Kagi.

      +
      + +
      +
    • Private browsing

      To search in Private Browsing, paste the Kagi private session link in the textbox below after copying it from your Kagi account settings.

      - -
      + +
    diff --git a/safari/Universal/Shared (Extension)/Resources/popup.js b/safari/Universal/Shared (Extension)/Resources/popup.js index e297bdc..0c59e40 100644 --- a/safari/Universal/Shared (Extension)/Resources/popup.js +++ b/safari/Universal/Shared (Extension)/Resources/popup.js @@ -55,20 +55,6 @@ function paramsForKnownHosts(knownHosts) { } return params.filter((value, index, array) => array.indexOf(value) === index); } -// const extensionId = "com.kagi.Kagi-Search-for-Safari.Extension (TFVG979488)"; -// const userAgent = window.navigator.userAgent, -// platform = window.navigator?.userAgentData?.platform || window.navigator.platform, -// macosPlatforms = ['macOS', 'Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], -// iosPlatforms = ['iPhone', 'iPad', 'iPod']; -// document.getElementById("open-app").onclick = function() { -// if (macosPlatforms.indexOf(platform) !== -1) { -// browser.runtime.sendNativeMessage(extensionId, {"type": "openApp"}, function(response) { -// window.close(); -// }); -// } else if (iosPlatforms.indexOf(platform) !== -1) { -// window.open("kagisearch://") -// } -// } // ----------------------- // MARK: - Private session link handling @@ -91,7 +77,42 @@ function privateSessionLinkTextfieldChanged(evt) { document.querySelector("#private-session-link").addEventListener('change', privateSessionLinkTextfieldChanged); document.querySelector("#private-session-link").addEventListener('paste', privateSessionLinkTextfieldChanged); - + + +// ----------------------- +// MARK: - Selecting default engine to redirect +// ----------------------- +var engineToRedirect = "All"; +const defaultEngineToRedirect = "Google"; +const engineSelect = document.getElementById('engine-to-redirect'); + +// Updates the UI +function selectCurrentEngine(currentEngine) { + selectCurrentEngineIndex(Array.from(engineSelect.options).indexOf(engineSelect.namedItem(currentEngine))); +} +function selectCurrentEngineIndex(engineIndex) { + engineSelect.selectedIndex = engineIndex; +} + +// Runs when the selection changes +function engineToRedirectChanged() { + const index = engineSelect.selectedIndex; + updateEngineToRedirect(engineSelect.options[index].value); +} + +// Stores the new engine in storage +function updateEngineToRedirect(newEngine) { + engineToRedirect = newEngine; + selectCurrentEngine(newEngine); + return browser.storage.local.set({ "kagiEngineToRedirect": newEngine }) + .then((result) => { + browser.runtime.sendMessage({ + "updatedKagiEngineToRedirect": newEngine + }); + }); +} + +engineSelect.addEventListener('change', engineToRedirectChanged); // ----------------------- // MARK: - Displaying & updating host permissions @@ -105,6 +126,47 @@ function fetchAndUpdateKnownHostList() { enabledElement.classList.toggle("enabledForThisDomain", hasKnownHosts); enabledElement.innerText = hasKnownHosts ? "enabled on:" : "disabled"; updateKnownHostList(knownHosts); + + // If the currently-redirecting engine no longer has permissions in the extension, + // reset to "All" + let enginesToDisplayInRedirectList = Array.from(document.querySelectorAll("[data-engine]")).map((en) => en.getAttribute("data-engine")); + if (engineToRedirect != "All" && enginesToDisplayInRedirectList.indexOf(engineToRedirect) < 0) { + engineToRedirect = "All"; + } + + // If we're still set to "All", update to the default + // FIXME: "All" is a fallback in case something else breaks in our stored engine setting, to make sure "Redirect to Kagi" is the fallback to broken engine selection rather than "Don't redirect if we don't have a valid engine selected". There should be a more robust solution to this that sets smart defaults or detects Safari's search engine setting. There's a way to do the latter on macOS but not iOS. + if (engineToRedirect == "All") { + updateEngineToRedirect(defaultEngineToRedirect); // Need to default to *something*. Starting w/ Google + } + + // Redirect engine list UI updates + if (knownHosts.indexOf("*://*/*") > -1) { + // TODO: Do we need custom logic for the "All websites allowed" permission? + } else { + if (enginesToDisplayInRedirectList.length > 0) { + for (let i=0;i 0) { -// let engineMatchPatterns = engineToRevoke == "All" ? ["*://*/*"] : domainMap[engineToRevoke].map((domain) => `*://*.${domain}/*`); -// revokeHostPermissions(engineMatchPatterns); -// } else { -// let hostToRevoke = evt.currentTarget.getAttribute("data-host"); -// let hostMatchPattern = `*://*.${hostToRevoke.replace(/^www\./, "")}/*`; // "www" removal should be redundant, but leaving replacement here for safety in future situations -// revokeHostPermissions([hostMatchPattern]); -// } } else { el.classList.add("readyToConfirm"); } @@ -226,32 +275,28 @@ document.onclick = function (e) { // MARK: - Onload handler // ----------------------- document.addEventListener("DOMContentLoaded", (event) => { -// browser.tabs.query({ currentWindow: true, active: true }) -// .then((tabs) => { -// if (tabs.length != 1) { -// Promise.reject(new Error("activeTab request did not return only 1 tab")); -// } -// -// console.log("Returned first tab:", tabs[0]); -// let url = new URL(tabs[0].url); -// document.getElementById("currentHost").innerText = url.hostname; -// }) - Promise.all([ - fetchAndUpdateKnownHostList(), - browser.storage.local.get("kagiPrivateSessionLink") - ]) + browser.storage.local.get(["kagiEngineToRedirect", "kagiPrivateSessionLink"]) .then((results) => { + // Fetch the current engine to redirect from local storage + if (typeof results == "object" && + typeof results["kagiEngineToRedirect"] == "string" + && results["kagiEngineToRedirect"].length > 0) { + engineToRedirect = results["kagiEngineToRedirect"]; + } // Fetch the current private session link from storage - let localPrivateSessionLink = results[1]; - if (typeof localPrivateSessionLink == "object" && - typeof localPrivateSessionLink["kagiPrivateSessionLink"] == "string" - && localPrivateSessionLink["kagiPrivateSessionLink"].length > 0) { - privateSessionLink = localPrivateSessionLink["kagiPrivateSessionLink"]; + if (typeof results == "object" && + typeof results["kagiPrivateSessionLink"] == "string" + && results["kagiPrivateSessionLink"].length > 0) { + privateSessionLink = results["kagiPrivateSessionLink"]; document.querySelector("#private-session-link").value = privateSessionLink; } + }) + .finally(() => { + selectCurrentEngine(engineToRedirect); + fetchAndUpdateKnownHostList(); }); }); -const symbolTrashBase64ImgTag = ``; \ No newline at end of file +const symbolTrashBase64ImgTag = ``; diff --git a/safari/Universal/Shared (Extension)/Resources/manifest.json b/safari/Universal/iOS (Extension)/manifest.json similarity index 96% rename from safari/Universal/Shared (Extension)/Resources/manifest.json rename to safari/Universal/iOS (Extension)/manifest.json index 85e6b0b..26c52a6 100644 --- a/safari/Universal/Shared (Extension)/Resources/manifest.json +++ b/safari/Universal/iOS (Extension)/manifest.json @@ -4,7 +4,7 @@ "name": "__MSG_extension_name__", "description": "__MSG_extension_description__", - "version": "2.2.0", + "version": "2.2.2", "icons": { "512": "images/Icon.png" diff --git a/safari/Universal/macOS (Extension)/manifest.json b/safari/Universal/macOS (Extension)/manifest.json new file mode 100644 index 0000000..c864027 --- /dev/null +++ b/safari/Universal/macOS (Extension)/manifest.json @@ -0,0 +1,34 @@ +{ + "manifest_version": 2, + "default_locale": "en", + + "name": "__MSG_extension_name__", + "description": "__MSG_extension_description__", + "version": "2.2.2", + + "icons": { + "512": "images/Icon.png" + }, + + "background": { + "scripts": [ + "background.js" + ], + "persistent": false + }, + + "browser_action": { + "default_popup": "popup.html", + "default_icon": { + "128": "images/ToolbarItemIcon.pdf" + } + }, + + "permissions": [ + "nativeMessaging", + "webNavigation", + "storage" + ], + + "optional_permissions": [] +}