You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
6.3 KiB

/**
* fix-place 浏览器脚本(纯字符串)。禁止改为 function 传入 page.evaluate。
*/
export const INVOKE_CAPTURED_PLACE_CHANGED = `(arg) => {
const pid = arg.pid;
const desc = arg.desc;
const loc = arg.loc || {};
const handlers = window.__rpaPlaceChangedHandlers || [];
if (!handlers.length) {
return { ok: false, reason: "no-captured-handlers", handlerCount: 0 };
}
const active = document.activeElement;
const lat =
typeof loc.latitude === "number"
? loc.latitude
: typeof loc.lat === "number"
? loc.lat
: 0;
const lng =
typeof loc.longitude === "number"
? loc.longitude
: typeof loc.lng === "number"
? loc.lng
: 0;
const placePayload = {
place_id: pid,
formatted_address: desc,
name: (desc.split(",")[0] || "").trim(),
geometry: {
location: {
lat: function() { return lat; },
lng: function() { return lng; },
},
},
address_components: loc.addressComponents || loc.address_components || [],
};
const ordered = handlers.slice().reverse();
const activeInput =
active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA")
? active
: null;
const tryInvoke = function(entry) {
const inst = entry.instance;
const handler = entry.handler;
if (!inst || typeof handler !== "function") {
return { ok: false, reason: "bad-entry" };
}
const originalGetPlace =
typeof inst.getPlace === "function"
? inst.getPlace.bind(inst)
: function() { return {}; };
inst.getPlace = function() {
return placePayload;
};
try {
handler.call(inst);
return { ok: true, reason: "handler-invoked" };
} catch (e) {
return { ok: false, reason: "handler-threw:" + String(e) };
} finally {
setTimeout(function() {
inst.getPlace = originalGetPlace;
}, 120);
}
};
if (activeInput) {
for (let i = 0; i < ordered.length; i += 1) {
const entry = ordered[i];
if (entry.inputEl === activeInput) {
const result = tryInvoke(entry);
if (result.ok) {
return { ok: true, reason: result.reason, handlerCount: handlers.length };
}
}
}
}
for (let j = 0; j < ordered.length; j += 1) {
const fallback = tryInvoke(ordered[j]);
if (fallback.ok) {
return { ok: true, reason: fallback.reason, handlerCount: handlers.length };
}
}
return { ok: false, reason: "all-handlers-failed", handlerCount: handlers.length };
}`;
export const TRIGGER_GOOGLE_PLACE_CHANGED = `(arg) => {
const pid = arg.pid;
const desc = arg.desc;
const gmaps = window.google;
const resolveInstance = function() {
const instances = window.__rpaAutocompleteInstances || [];
if (instances.length > 0) {
return instances[instances.length - 1];
}
if (gmaps && gmaps.maps && gmaps.maps.places && gmaps.maps.places.Autocomplete) {
const AutocompleteCtor = gmaps.maps.places.Autocomplete;
const globalKeys = Object.keys(window).filter(function(k) {
try {
return window[k] instanceof AutocompleteCtor;
} catch (e) {
return false;
}
});
if (globalKeys.length > 0) {
return window[globalKeys[0]];
}
}
const pacInput =
document.querySelector(".pac-target-input") ||
document.querySelector("#react-quoter-landing-plugin input");
if (!pacInput) {
return null;
}
const keys = Object.keys(pacInput);
for (let i = 0; i < keys.length; i += 1) {
const key = keys[i];
if (key.indexOf("gm_") !== 0) continue;
const val = pacInput[key];
if (val && typeof val.getPlace === "function") {
return val;
}
}
return null;
};
const autocompleteInstance = resolveInstance();
if (!autocompleteInstance) {
return { ok: false, reason: "no-autocomplete-instance" };
}
if (!gmaps || !gmaps.maps || !gmaps.maps.event || typeof gmaps.maps.event.trigger !== "function") {
return { ok: false, reason: "google-maps-unavailable" };
}
const originalGetPlace = autocompleteInstance.getPlace.bind(autocompleteInstance);
autocompleteInstance.getPlace = function() {
return {
place_id: pid,
formatted_address: desc,
name: desc.split(",")[0],
geometry: { location: { lat: function() { return 0; }, lng: function() { return 0; } } },
};
};
gmaps.maps.event.trigger(autocompleteInstance, "place_changed");
setTimeout(function() {
autocompleteInstance.getPlace = originalGetPlace;
}, 100);
return { ok: true, reason: "triggered" };
}`;
export const CHECK_PICKUP_IN_REACT_STATE = `() => {
const widget = document.querySelector("#react-quoter-landing-plugin");
if (!widget) return false;
const fiberKey = Object.keys(widget).find(function(k) {
return k.indexOf("__reactFiber$") === 0 || k.indexOf("__reactInternalInstance$") === 0;
});
if (!fiberKey) return false;
let fiber = widget[fiberKey];
while (fiber) {
const state = fiber.stateNode && fiber.stateNode.state;
if (state) {
const pickup = state.pickupAddress || state.pickup || (state.addresses && state.addresses.pickup);
if (pickup && (pickup.placeId || pickup.formattedAddress)) {
return true;
}
}
fiber = fiber.return;
}
return false;
}`;
export const INJECT_REACT_STATE = `(arg) => {
const sideArg = arg.sideArg;
const pid = arg.pid;
const loc = arg.loc;
const desc = arg.desc;
const widget = document.querySelector("#react-quoter-landing-plugin");
if (!widget) return false;
const fiberKey = Object.keys(widget).find(function(k) {
return k.indexOf("__reactFiber$") === 0 || k.indexOf("__reactInternalInstance$") === 0;
});
if (!fiberKey) return false;
let fiber = widget[fiberKey];
while (fiber) {
const stateNode = fiber.stateNode;
if (stateNode && typeof stateNode.setState === "function") {
const state = stateNode.state;
if (state && ("pickupAddress" in state || "pickup" in state || "addresses" in state)) {
const addressData = {
placeId: pid,
location: loc,
formattedAddress: desc,
isCommitted: true,
};
const stateKey = sideArg === "pickup" ? "pickupAddress" : "deliveryAddress";
stateNode.setState({ [stateKey]: addressData });
return true;
}
}
fiber = fiber.return;
}
return false;
}`;