embed-fbcmt-client
Version:
client package for embed-fbcmt
309 lines (303 loc) • 7.47 kB
JavaScript
;
var vue = require('vue');
// src/constants.ts
var defaults = {
color_scheme: "light",
lazy: false,
mobile: void 0,
num_posts: 10,
order_by: "reverse_time",
lang: "en_US",
origin: "*",
no_socket: false,
active: true,
no_popup: false
};
// src/client/main.ts
function setPropValue(el, prop, value, origin) {
if (origin === void 0) {
origin = value;
value = void 0;
}
return new Promise((resolve, reject) => {
const id = (Number.MAX_SAFE_INTEGER * Math.random()).toString(34);
const handler = (event) => {
if (event.data?.type === "res::fb:set_value" && id === event.data.id) {
const { code } = event.data;
if (typeof code !== "string")
return;
if (code.startsWith("success."))
resolve();
else if (code.startsWith("error."))
reject(Object.assign(new Error(code), { prop }));
else
console.warn("[res::fb:set_value]: invalid code error '%s'", code);
cancel();
}
};
let timeout = null;
const cancel = () => {
if (timeout)
clearTimeout(timeout);
window.removeEventListener("message", handler);
};
window.addEventListener("message", handler);
timeout = setTimeout(() => {
cancel();
reject(new Error("error.timeout" /* ERROR_TIMEOUT */));
}, 3e4);
const res = {
id,
type: "req::fb:set_value",
props: typeof prop === "object" ? prop : { [prop]: value }
};
if (el.contentWindow)
el.contentWindow.postMessage(res, origin ?? "*");
else
reject();
});
}
function listenEvent(el, cb) {
const handler = (event) => {
if (event.source !== el.contentWindow)
return;
if (event.data?.type !== "emit::fb_embed")
return;
const typeCode = getTypeCode(event.data.code);
if (!typeCode)
return;
cb({
type: typeCode,
code: event.data.code,
message: event.data.message
});
};
window.addEventListener("message", handler);
return () => window.removeEventListener("message", handler);
}
function listenResize(el, type, cb) {
const handler = (event) => {
if (event.source !== el.contentWindow)
return;
if (event.data?.type !== `update::fb_${type}`)
return;
cb(event.data.value);
};
window.addEventListener("message", handler);
return () => window.removeEventListener("message", handler);
}
function getTypeCode(code) {
if (code.startsWith("success."))
return "success";
if (code.startsWith("loading."))
return "loading";
if (code.startsWith("error."))
return "error";
return null;
}
var EmbedFbCmt_default = vue.defineComponent({
props: {
color_scheme: {
type: String,
default: defaults.color_scheme
},
href: {
type: String,
required: true
},
lazy: {
type: Boolean,
default: defaults.lazy
},
mobile: {
type: Boolean,
default: defaults.mobile
},
num_posts: {
type: Number,
default: defaults.num_posts
},
order_by: {
type: String,
default: defaults.order_by
},
lang: {
type: String,
default: defaults.lang
},
origin: {
type: String,
default: defaults.origin
},
no_socket: {
type: Boolean,
default: defaults.no_socket
},
active: {
type: Boolean,
default: defaults.active
},
no_popup: {
type: Boolean,
default: defaults.no_popup
},
service: {
type: String,
default: "https://anime-vsub.github.io/embed-fbcmt"
}
},
setup(props) {
const rootSrc = vue.ref();
vue.watch(
() => props.service,
(service) => {
const query = new URLSearchParams(
props
);
query.delete("service");
rootSrc.value = new URL(`?${query}`, service).toString();
},
{ immediate: true }
);
const commentRef = vue.ref();
vue.watch(props, async (props2) => {
const cloned = { ...props2 };
delete cloned.service;
await setPropValue2(commentRef, cloned);
});
const height = useEmbedHeight(commentRef);
return () => vue.h("iframe", {
src: rootSrc.value,
ref: commentRef,
frameborder: "0",
allowtransparency: "true",
allowfullscreen: "true",
scrolling: "no",
width: "100%",
height: "100%",
allow: "encrypted-media",
sandbox: "allow-forms allow-scripts allow-same-origin allow-top-navigation allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox",
style: { height: `${height.value}px` }
});
}
});
// src/client/vue.ts
function isComponent(el) {
return typeof el.$el !== "undefined";
}
function useEmbed(el) {
const code = vue.ref({
code: "pending" /* PENDING */
});
const loading = vue.ref(false);
const error = vue.ref();
let cancelListenEvent = null;
if (!vue.isRef(el))
el = vue.ref(el);
vue.watch(
el,
(el2) => {
if (isComponent(el2))
el2 = el2.$el;
cancelListenEvent?.();
loading.value = false;
error.value = void 0;
code.value = {
code: "pending" /* PENDING */
};
if (!el2)
return;
cancelListenEvent = listenEvent(el2, (event) => {
code.value = event;
if (event.type === "loading") {
error.value = void 0;
loading.value = true;
} else if (event.type === "error") {
loading.value = false;
error.value = Object.assign(new Error(event.message), {
code: event.type
});
} else {
loading.value = false;
error.value = void 0;
}
});
},
{ immediate: true }
);
vue.onBeforeUnmount(() => cancelListenEvent?.());
return { code, loading, error };
}
function useEmbedSize(el) {
let cancelResizWEvent = null;
let cancelResizHEvent = null;
const width = vue.ref(0);
const height = vue.ref(0);
if (!vue.isRef(el))
el = vue.ref(el);
vue.watch(el, (el2) => {
if (isComponent(el2))
el2 = el2.$el;
cancelResizWEvent?.();
cancelResizHEvent?.();
if (!el2)
return;
cancelResizWEvent = listenResize(
el2,
"width",
(value) => width.value = value
);
cancelResizHEvent = listenResize(
el2,
"height",
(value) => height.value = value
);
});
vue.onBeforeUnmount(() => {
cancelResizWEvent?.();
cancelResizHEvent?.();
});
return { width, height };
}
function useEmbedHeight(el) {
let cancelResizHEvent = null;
const height = vue.ref(0);
if (!vue.isRef(el))
el = vue.ref(el);
vue.watch(el, (el2) => {
if (isComponent(el2))
el2 = el2.$el;
cancelResizHEvent?.();
if (!el2)
return;
cancelResizHEvent = listenResize(
el2,
"height",
(value) => height.value = value
);
});
vue.onBeforeUnmount(() => {
cancelResizHEvent?.();
});
return height;
}
async function setPropValue2(el, prop, value, origin) {
if (vue.isRef(el))
el = el.value;
if (isComponent(el))
el = el.$el;
if (el) {
await setPropValue(
el,
prop,
value,
origin
);
}
}
exports.EmbedFbCmt = EmbedFbCmt_default;
exports.listenResize = listenResize;
exports.setPropValue = setPropValue2;
exports.useEmbed = useEmbed;
exports.useEmbedHeight = useEmbedHeight;
exports.useEmbedSize = useEmbedSize;