diff --git a/src/popup/App.svelte b/src/popup/App.svelte index f12154c7..f4bb1998 100644 --- a/src/popup/App.svelte +++ b/src/popup/App.svelte @@ -27,6 +27,7 @@ let inactive = false; let platform; let initError; + let firstGuide; let windowHeight = 0; let header; let warn; @@ -220,6 +221,13 @@ loading = false; } + async function openContainingApp() { + browser.tabs.executeScript({ + code: `location="${firstGuide}"` + }); + window.close(); + } + async function initialize() { // get platform first since it applies important styling let pltfm; @@ -239,31 +247,23 @@ } platform = pltfm.platform; - // run init checks - // const init = await browser.runtime.sendNativeMessage({name: "POPUP_INIT"}).catch(error => {}); - let init; - try { - init = await browser.runtime.sendNativeMessage({name: "POPUP_INIT"}); - } catch (error) { - console.error(`Error for init promise: ${error}`); - initError = true; - loading = false; - return; - } - if (init.error) { - errorNotification = init.error; + // display native error if there is + const errorNative = await settingsStorage.get("error_native"); + if (errorNative.error) { + if (errorNative.saveLocation === "unset") { + firstGuide = `${errorNative.scheme}://`; + loading = false; + return; + } + errorNotification = errorNative.error; loading = false; disabled = false; return; } + // set toggle state active = await settingsStorage.get("global_active"); - // refresh session rules - browser.runtime.sendMessage({name: "REFRESH_SESSION_RULES"}); - // refresh context-menu scripts - browser.runtime.sendMessage({name: "REFRESH_CONTEXT_MENU_SCRIPTS"}); - // set popup height resize(); @@ -542,6 +542,11 @@ {:else} {#if inactive}
Popup inactive on extension page
+ {:else if firstGuide} +
+ Welcome, first please:  + set directory +
{:else if initError}
Something went wrong:  diff --git a/src/shared/dev.js b/src/shared/dev.js index 9b1037d2..03ab9296 100644 --- a/src/shared/dev.js +++ b/src/shared/dev.js @@ -265,37 +265,6 @@ const _browser = { } ] }; - } else if (name === "POPUP_INIT") { - response.initData = { - active: "true", - items: [ - { - name: "Google Images Restored", - filename: "Google Images Restored.js", - disabled: false, - type: "js" - }, - { - name: "Subframe Script Managerial Staffing Company", - filename: "Subframe Script.js", - disabled: false, - subframe: true, - type: "css" - } - ], - updates: [ - { - filename: "Google Images Restored.js", - name: "Google Images Restored", - url: "https://www.k21p.com" - }, - { - filename: "New Userscript With a Really Really Long Name.js", - name: "New Userscript With a Really Really Long Name", - url: "https://www.filmgarb.com" - } - ] - }; } else if (name === "POPUP_MATCHES") { response = { matches: [ diff --git a/src/shared/settings.js b/src/shared/settings.js index 2a68635c..059870b6 100644 --- a/src/shared/settings.js +++ b/src/shared/settings.js @@ -41,6 +41,14 @@ const settingDefault = deepFreeze({ }); export const settingsDefine = deepFreeze([ + { + name: "error_native", + type: "object", + local: true, + default: {error: undefined}, + platforms: ["macos", "ipados", "ios"], + group: "Internal" + }, { name: "legacy_imported", type: "number", @@ -173,8 +181,7 @@ export const settingsDefine = deepFreeze([ en: "The lasttime for script update check in background", zh_hans: "后台脚本更新上次检查时间" }, - group: "Internal", - nodeType: "Toggle" + group: "Internal" }, { name: "scripts_auto_update", diff --git a/xcode/Safari-Extension/Functions.swift b/xcode/Safari-Extension/Functions.swift index 8e5fcffb..b65558cf 100644 --- a/xcode/Safari-Extension/Functions.swift +++ b/xcode/Safari-Extension/Functions.swift @@ -1911,62 +1911,58 @@ func getFileRemoteUpdate(_ content: String) -> [String: String] { return ["content": remoteContent] } -func popupInit() -> [String: String]? { +// background +func nativeChecks() -> [String: String] { + logText("nativeChecks started") + #if os(iOS) + // check the save location is set + guard (getSaveLocation() != nil) else { + err("nativeChecks: save location unset (iOS)") + return [ + "error": "Native checks error (0)", + "saveLocation": "unset", + "scheme": Bundle.main.infoDictionary?["US_URL_SCHEME"] as! String + ] + } + #endif // check the default directories - let checkDefaultDirectories = checkDefaultDirectories() + guard checkDefaultDirectories() else { + err("nativeChecks: checkDefaultDirectories failed") + return ["error": "Native checks error (1)"] + } // check the settings - let checkSettings = checkSettings() + guard checkSettings() else { + err("nativeChecks: checkSettings failed") + return ["error": "Native checks error (2)"] + } // get all files to pass as arguments to function below guard let allFiles = getAllFiles() else { - err("Failed to getAllFiles in popupInit") - return nil + err("nativeChecks: getAllFiles failed") + return ["error": "Native checks error (3)"] } // purge the manifest of old records - let purgeManifest = purgeManifest(allFiles) - // update matches in manifest - let updateManifestMatches = updateManifestMatches(allFiles) - // update the required resources - let updateManifestRequired = updateManifestRequired(allFiles) - // update declarativeNetRequest - let updateDeclarativeNetRequest = updateManifestDeclarativeNetRequests(allFiles) - // verbose error checking - if !checkDefaultDirectories { - err("Failed to checkDefaultDirectories in popupInit") - return nil - } - if !checkSettings { - err("Failed to checkSettings in popupInit") - return nil - } - if !purgeManifest { - err("Failed to purgeManifest in popupInit") - return nil + guard purgeManifest(allFiles) else { + err("nativeChecks: purgeManifest failed") + return ["error": "Native checks error (4)"] } - if !updateManifestMatches { - err("Failed to updateManifestMatches in popupInit") - return nil + // update matches in manifest + guard updateManifestMatches(allFiles) else { + err("nativeChecks: updateManifestMatches failed") + return ["error": "Native checks error (5)"] } - if !updateManifestRequired { - err("Failed to updateManifestRequired in popupInit") - return nil + // update the required resources + guard updateManifestRequired(allFiles) else { + err("nativeChecks: updateManifestRequired failed") + return ["error": "Native checks error (6)"] } - if !updateDeclarativeNetRequest { - err("Failed to updateDeclarativeNetRequest in popupInit") - return nil + // update declarativeNetRequest + guard updateManifestDeclarativeNetRequests(allFiles) else { + err("nativeChecks: updateManifestDeclarativeNetRequests failed") + return ["error": "Native checks error (7)"] } // pass some info in response - guard let saveLocation = getSaveLocation() else { - err("Failed at getSaveLocation in popupInit") - return nil - } - let documentsDirectory = getDocumentsDirectory() - let requireLocation = getRequireLocation() - - return [ - "saveLocation": saveLocation.absoluteString, - "documentsDirectory": documentsDirectory.absoluteString, - "requireLocation": requireLocation.absoluteString - ] + logText("nativeChecks complete") + return ["success": "Native checks complete"] } // userscript install diff --git a/xcode/Safari-Extension/Resources/background.js b/xcode/Safari-Extension/Resources/background.js index 32708caa..42376d00 100644 --- a/xcode/Safari-Extension/Resources/background.js +++ b/xcode/Safari-Extension/Resources/background.js @@ -129,6 +129,12 @@ async function setBadgeCount() { }); } +// on startup get declarativeNetRequests +// and set the requests for the session +// should also check and refresh when: +// 1. dnr item save event in the page occurs +// 2. dnr item toggle event in the page occurs +// 3. external editor changes script file content async function setSessionRules() { // not supported below safari 15.4 if (!browser.declarativeNetRequest.updateSessionRules) return; @@ -187,6 +193,9 @@ function randomNumberSet(max, count) { return [...numbers]; } +// the current update logic is similar to setSessionRules() +// this feature needs a more detailed redesign in the future +// https://github.com/quoid/userscripts/issues/453 async function getContextMenuItems() { // macos exclusive feature const platform = await getPlatform(); @@ -273,6 +282,17 @@ function contextClick(info, tab) { }); } +async function nativeChecks() { + const response = await browser.runtime.sendNativeMessage({name: "NATIVE_CHECKS"}); + // note: use settings.js once background page modularization + if (response.error) { + browser.storage.local.set({US_ERROR_NATIVE: response}); + return false; + } + browser.storage.local.remove("US_ERROR_NATIVE"); + return true; +} + // handles messages sent with browser.runtime.sendMessage function handleMessage(request, sender, sendResponse) { switch (request.name) { @@ -455,22 +475,26 @@ function handleMessage(request, sender, sendResponse) { } } } - +browser.runtime.onInstalled.addListener(async () => { + nativeChecks(); +}); browser.runtime.onStartup.addListener(async () => { - // on startup get declarativeNetRequests - // and set the requests for the session - // should also check and refresh when: - // 1. popup opens (done) - // 2. a new save event in the page occurs - // 3. the refresh button is pushed in the popup - await setSessionRules(); - await getContextMenuItems(); + setSessionRules(); + getContextMenuItems(); }); // listens for messages from content script, popup and page browser.runtime.onMessage.addListener(handleMessage); // set the badge count browser.tabs.onActivated.addListener(setBadgeCount); -browser.windows.onFocusChanged.addListener(setBadgeCount); +browser.windows.onFocusChanged.addListener(async windowId => { + if (windowId < 1) { // lose focus + return; + } + nativeChecks(); + setBadgeCount(); + setSessionRules(); + getContextMenuItems(); +}); browser.webNavigation.onCompleted.addListener(setBadgeCount); // handle native app messages diff --git a/xcode/Safari-Extension/SafariWebExtensionHandler.swift b/xcode/Safari-Extension/SafariWebExtensionHandler.swift index 8f64175c..76364f59 100644 --- a/xcode/Safari-Extension/SafariWebExtensionHandler.swift +++ b/xcode/Safari-Extension/SafariWebExtensionHandler.swift @@ -25,6 +25,10 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { #endif } } + else if name == "NATIVE_CHECKS" { + let result = nativeChecks() + response.userInfo = [SFExtensionMessageKey: result] + } else if name == "REQ_PLATFORM" { let platform = getPlatform() response.userInfo = [SFExtensionMessageKey: ["platform": platform]] @@ -68,13 +72,6 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { inBoundError = true } } - else if name == "POPUP_INIT" { - if let initData = popupInit() { - response.userInfo = [SFExtensionMessageKey: ["initData": initData]] - } else { - response.userInfo = [SFExtensionMessageKey: ["error": "failed to get init data"]] - } - } else if name == "POPUP_MATCHES"{ if let url = message?["url"] as? String, let frameUrls = message?["frameUrls"] as? [String] { if let matches = getPopupMatches(url, frameUrls) { diff --git a/xcode/iOS-App/Info.plist b/xcode/iOS-App/Info.plist index a2a30aa2..a5539a85 100644 --- a/xcode/iOS-App/Info.plist +++ b/xcode/iOS-App/Info.plist @@ -2,6 +2,19 @@ + CFBundleURLTypes + + + CFBundleTypeRole + Viewer + CFBundleURLName + $(APP_IDENTIFIER) + CFBundleURLSchemes + + $(APP_URL_SCHEME) + + + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes