telegram: modularize, add to userpage
This commit is contained in:
+35
-50
@@ -3,7 +3,7 @@ import { notificationBox, whichAnimationEvent } from "./modules/common.js";
|
||||
import { _get, _post, toggleLoader, addLoader, removeLoader, toDateString } from "./modules/common.js";
|
||||
import { loadLangSelector } from "./modules/lang.js";
|
||||
import { initValidator } from "./modules/validator.js";
|
||||
import { Discord, DiscordConfiguration } from "./modules/account-linking.js";
|
||||
import { Discord, Telegram, ServiceConfiguration } from "./modules/account-linking.js";
|
||||
|
||||
interface formWindow extends Window {
|
||||
invalidPassword: string;
|
||||
@@ -50,46 +50,31 @@ var telegramVerified = false;
|
||||
if (window.telegramEnabled) {
|
||||
window.telegramModal = new Modal(document.getElementById("modal-telegram"), window.telegramRequired);
|
||||
const telegramButton = document.getElementById("link-telegram") as HTMLSpanElement;
|
||||
telegramButton.onclick = () => {
|
||||
const waiting = document.getElementById("telegram-waiting") as HTMLSpanElement;
|
||||
toggleLoader(waiting);
|
||||
window.telegramModal.show();
|
||||
let modalClosed = false;
|
||||
window.telegramModal.onclose = () => {
|
||||
modalClosed = true;
|
||||
toggleLoader(waiting);
|
||||
|
||||
const telegramConf: ServiceConfiguration = {
|
||||
modal: window.telegramModal as Modal,
|
||||
pin: window.telegramPIN,
|
||||
pinURL: "",
|
||||
verifiedURL: "/invite/" + window.code + "/telegram/verified/",
|
||||
invalidCodeError: window.messages["errorInvalidCode"],
|
||||
accountLinkedError: window.messages["errorAccountLinked"],
|
||||
successError: window.messages["verified"],
|
||||
successFunc: (modalClosed: boolean) => {
|
||||
if (modalClosed) return;
|
||||
telegramVerified = true;
|
||||
telegramButton.classList.add("unfocused");
|
||||
document.getElementById("contact-via").classList.remove("unfocused");
|
||||
document.getElementById("contact-via-email").parentElement.classList.remove("unfocused");
|
||||
const radio = document.getElementById("contact-via-telegram") as HTMLInputElement;
|
||||
radio.parentElement.classList.remove("unfocused");
|
||||
radio.checked = true;
|
||||
validatorFunc();
|
||||
}
|
||||
const checkVerified = () => _get("/invite/" + window.code + "/telegram/verified/" + window.telegramPIN, null, (req: XMLHttpRequest) => {
|
||||
if (req.readyState == 4) {
|
||||
if (req.status == 401) {
|
||||
window.telegramModal.close();
|
||||
window.notifications.customError("invalidCodeError", window.messages["errorInvalidCode"]);
|
||||
return;
|
||||
} else if (req.status == 400) {
|
||||
window.telegramModal.close();
|
||||
window.notifications.customError("accountLinkedError", window.messages["errorAccountLinked"]);
|
||||
} else if (req.status == 200) {
|
||||
if (req.response["success"] as boolean) {
|
||||
telegramVerified = true;
|
||||
waiting.classList.add("~positive");
|
||||
waiting.classList.remove("~info");
|
||||
window.notifications.customPositive("telegramVerified", "", window.messages["verified"]);
|
||||
setTimeout(window.telegramModal.close, 2000);
|
||||
telegramButton.classList.add("unfocused");
|
||||
document.getElementById("contact-via").classList.remove("unfocused");
|
||||
document.getElementById("contact-via-email").parentElement.classList.remove("unfocused");
|
||||
const radio = document.getElementById("contact-via-telegram") as HTMLInputElement;
|
||||
radio.parentElement.classList.remove("unfocused");
|
||||
radio.checked = true;
|
||||
validatorFunc();
|
||||
} else if (!modalClosed) {
|
||||
setTimeout(checkVerified, 1500);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
checkVerified();
|
||||
};
|
||||
|
||||
const telegram = new Telegram(telegramConf);
|
||||
|
||||
telegramButton.onclick = () => { telegram.onclick(); };
|
||||
}
|
||||
|
||||
var discordVerified = false;
|
||||
@@ -97,7 +82,7 @@ if (window.discordEnabled) {
|
||||
window.discordModal = new Modal(document.getElementById("modal-discord"), window.discordRequired);
|
||||
const discordButton = document.getElementById("link-discord") as HTMLSpanElement;
|
||||
|
||||
const discordConf: DiscordConfiguration = {
|
||||
const discordConf: ServiceConfiguration = {
|
||||
modal: window.discordModal as Modal,
|
||||
pin: window.discordPIN,
|
||||
inviteURL: window.discordInviteLink ? ("/invite/" + window.code + "/discord/invite") : "",
|
||||
@@ -107,21 +92,21 @@ if (window.discordEnabled) {
|
||||
accountLinkedError: window.messages["errorAccountLinked"],
|
||||
successError: window.messages["verified"],
|
||||
successFunc: (modalClosed: boolean) => {
|
||||
if (!modalClosed) {
|
||||
discordButton.classList.add("unfocused");
|
||||
document.getElementById("contact-via").classList.remove("unfocused");
|
||||
document.getElementById("contact-via-email").parentElement.classList.remove("unfocused");
|
||||
const radio = document.getElementById("contact-via-discord") as HTMLInputElement;
|
||||
radio.parentElement.classList.remove("unfocused")
|
||||
radio.checked = true;
|
||||
validatorFunc();
|
||||
}
|
||||
if (modalClosed) return;
|
||||
discordVerified = true;
|
||||
discordButton.classList.add("unfocused");
|
||||
document.getElementById("contact-via").classList.remove("unfocused");
|
||||
document.getElementById("contact-via-email").parentElement.classList.remove("unfocused");
|
||||
const radio = document.getElementById("contact-via-discord") as HTMLInputElement;
|
||||
radio.parentElement.classList.remove("unfocused")
|
||||
radio.checked = true;
|
||||
validatorFunc();
|
||||
}
|
||||
};
|
||||
|
||||
const discord = new Discord(discordConf);
|
||||
|
||||
discordButton.onclick = discord.onclick;
|
||||
discordButton.onclick = () => { discord.onclick(); };
|
||||
}
|
||||
|
||||
var matrixVerified = false;
|
||||
|
||||
@@ -35,10 +35,10 @@ interface formWindow extends Window {
|
||||
|
||||
declare var window: formWindow;
|
||||
|
||||
export interface DiscordConfiguration {
|
||||
export interface ServiceConfiguration {
|
||||
modal: Modal;
|
||||
pin: string;
|
||||
inviteURL: string;
|
||||
inviteURL?: string;
|
||||
pinURL: string;
|
||||
verifiedURL: string;
|
||||
invalidCodeError: string;
|
||||
@@ -52,16 +52,17 @@ export interface DiscordInvite {
|
||||
icon: string;
|
||||
}
|
||||
|
||||
export class Discord {
|
||||
private _conf: DiscordConfiguration;
|
||||
private _pinAcquired = false;
|
||||
private _modalClosed = false;
|
||||
private _waiting = document.getElementById("discord-waiting") as HTMLSpanElement;
|
||||
private _verified = false;
|
||||
export class ServiceLinker {
|
||||
protected _conf: ServiceConfiguration;
|
||||
protected _pinAcquired = false;
|
||||
protected _modalClosed = false;
|
||||
protected _waiting: HTMLSpanElement;
|
||||
protected _verified = false;
|
||||
protected _name: string;
|
||||
|
||||
get verified(): boolean { return this._verified; }
|
||||
|
||||
constructor(conf: DiscordConfiguration) {
|
||||
constructor(conf: ServiceConfiguration) {
|
||||
this._conf = conf;
|
||||
this._conf.modal.onclose = () => {
|
||||
this._modalClosed = true;
|
||||
@@ -69,24 +70,7 @@ export class Discord {
|
||||
};
|
||||
}
|
||||
|
||||
private _getInviteURL = () => _get(this._conf.inviteURL, null, (req: XMLHttpRequest) => {
|
||||
if (req.readyState != 4) return;
|
||||
const inv = req.response as DiscordInvite;
|
||||
const link = document.getElementById("discord-invite") as HTMLAnchorElement;
|
||||
link.href = inv.invite;
|
||||
link.target = "_blank";
|
||||
let innerHTML = `<span class="mr-2">${window.lang.strings("joinTheServer")}</span>`;
|
||||
if (inv.icon != "") {
|
||||
innerHTML += `<span class="img-circle lg mr-4"><img class="img-circle" src="${inv.icon}" width="64" height="64"></span>${window.discordServerName}`;
|
||||
} else {
|
||||
innerHTML += `
|
||||
<span class="shield mr-4 bg-discord"><i class="ri-discord-fill ri-xl text-white"></i></span>${window.discordServerName}
|
||||
`;
|
||||
}
|
||||
link.innerHTML = innerHTML;
|
||||
});
|
||||
|
||||
private _checkVerified = () => {
|
||||
protected _checkVerified = () => {
|
||||
if (this._modalClosed) return;
|
||||
if (!this._pinAcquired) {
|
||||
setTimeout(this._checkVerified, 1500);
|
||||
@@ -105,7 +89,7 @@ export class Discord {
|
||||
this._verified = true;
|
||||
this._waiting.classList.add("~positive");
|
||||
this._waiting.classList.remove("~info");
|
||||
window.notifications.customPositive("discordVerified", "", this._conf.successError);
|
||||
window.notifications.customPositive(this._name + "Verified", "", this._conf.successError);
|
||||
if (this._conf.successFunc) {
|
||||
this._conf.successFunc(false);
|
||||
}
|
||||
@@ -123,18 +107,14 @@ export class Discord {
|
||||
});
|
||||
};
|
||||
|
||||
onclick = () => {
|
||||
if (this._conf.inviteURL != "") {
|
||||
this._getInviteURL();
|
||||
}
|
||||
|
||||
onclick() {
|
||||
toggleLoader(this._waiting);
|
||||
|
||||
this._pinAcquired = false;
|
||||
if (this._conf.pin) {
|
||||
this._pinAcquired = true;
|
||||
this._conf.modal.modal.querySelector(".pin").textContent = this._conf.pin;
|
||||
} else {
|
||||
} else if (this._conf.pinURL) {
|
||||
_get(this._conf.pinURL, null, (req: XMLHttpRequest) => {
|
||||
if (req.readyState == 4 && req.status == 200) {
|
||||
this._conf.pin = req.response["pin"];
|
||||
@@ -150,3 +130,45 @@ export class Discord {
|
||||
this._checkVerified();
|
||||
}
|
||||
}
|
||||
|
||||
export class Discord extends ServiceLinker {
|
||||
|
||||
constructor(conf: ServiceConfiguration) {
|
||||
super(conf);
|
||||
this._name = "discord";
|
||||
this._waiting = document.getElementById("discord-waiting") as HTMLSpanElement;
|
||||
}
|
||||
|
||||
private _getInviteURL = () => _get(this._conf.inviteURL, null, (req: XMLHttpRequest) => {
|
||||
if (req.readyState != 4) return;
|
||||
const inv = req.response as DiscordInvite;
|
||||
const link = document.getElementById("discord-invite") as HTMLSpanElement;
|
||||
(link.parentElement as HTMLAnchorElement).href = inv.invite;
|
||||
(link.parentElement as HTMLAnchorElement).target = "_blank";
|
||||
let innerHTML = ``;
|
||||
if (inv.icon != "") {
|
||||
innerHTML += `<span class="img-circle lg mr-4"><img class="img-circle" src="${inv.icon}" width="64" height="64"></span>${window.discordServerName}`;
|
||||
} else {
|
||||
innerHTML += `
|
||||
<span class="shield mr-4 bg-discord"><i class="ri-discord-fill ri-xl text-white"></i></span>${window.discordServerName}
|
||||
`;
|
||||
}
|
||||
link.innerHTML = innerHTML;
|
||||
});
|
||||
|
||||
onclick() {
|
||||
if (this._conf.inviteURL != "") {
|
||||
this._getInviteURL();
|
||||
}
|
||||
|
||||
super.onclick();
|
||||
}
|
||||
}
|
||||
|
||||
export class Telegram extends ServiceLinker {
|
||||
constructor(conf: ServiceConfiguration) {
|
||||
super(conf);
|
||||
this._name = "telegram";
|
||||
this._waiting = document.getElementById("telegram-waiting") as HTMLSpanElement;
|
||||
}
|
||||
};
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "../js",
|
||||
"target": "es6",
|
||||
"target": "es2017",
|
||||
"lib": ["dom", "es2017"],
|
||||
"typeRoots": ["./typings", "../node_modules/@types"],
|
||||
"moduleResolution": "node",
|
||||
"moduleResolution": "nodenext",
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
||||
|
||||
+22
-4
@@ -3,7 +3,7 @@ import { lang, LangFile, loadLangSelector } from "./modules/lang.js";
|
||||
import { Modal } from "./modules/modal.js";
|
||||
import { _get, _post, notificationBox, whichAnimationEvent, toDateString, toggleLoader } from "./modules/common.js";
|
||||
import { Login } from "./modules/login.js";
|
||||
import { Discord, DiscordConfiguration } from "./modules/account-linking.js";
|
||||
import { Discord, Telegram, ServiceConfiguration } from "./modules/account-linking.js";
|
||||
|
||||
interface userWindow extends Window {
|
||||
jellyfinID: string;
|
||||
@@ -285,7 +285,7 @@ const addEditEmail = (add: boolean): void => {
|
||||
window.modals.email.show();
|
||||
}
|
||||
|
||||
const discordConf: DiscordConfiguration = {
|
||||
const discordConf: ServiceConfiguration = {
|
||||
modal: window.modals.discord as Modal,
|
||||
pin: "",
|
||||
inviteURL: window.discordInviteLink ? "/my/discord/invite" : "",
|
||||
@@ -301,6 +301,21 @@ const discordConf: DiscordConfiguration = {
|
||||
|
||||
let discord = new Discord(discordConf);
|
||||
|
||||
const telegramConf: ServiceConfiguration = {
|
||||
modal: window.modals.telegram as Modal,
|
||||
pin: "",
|
||||
pinURL: "/my/pin/telegram",
|
||||
verifiedURL: "/my/telegram/verified/",
|
||||
invalidCodeError: window.lang.notif("errorInvalidCode"),
|
||||
accountLinkedError: window.lang.notif("errorAccountLinked"),
|
||||
successError: window.lang.notif("verified"),
|
||||
successFunc: (modalClosed: boolean) => {
|
||||
if (modalClosed) window.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
let telegram = new Telegram(telegramConf);
|
||||
|
||||
document.addEventListener("details-reload", () => {
|
||||
_get("/my/details", null, (req: XMLHttpRequest) => {
|
||||
if (req.readyState == 4) {
|
||||
@@ -325,10 +340,13 @@ document.addEventListener("details-reload", () => {
|
||||
|
||||
contactMethodList.clear();
|
||||
|
||||
// Note the weird format of the functions for discord/telegram:
|
||||
// "this" was being redefined within the onclick() method, so
|
||||
// they had to be wrapped in an anonymous function.
|
||||
const contactMethods: { name: string, icon: string, f: (add: boolean) => void }[] = [
|
||||
{name: "email", icon: `<i class="ri-mail-fill ri-lg"></i>`, f: addEditEmail},
|
||||
{name: "discord", icon: `<i class="ri-discord-fill ri-lg"></i>`, f: discord.onclick},
|
||||
{name: "telegram", icon: `<i class="ri-telegram-fill ri-lg"></i>`, f: null},
|
||||
{name: "discord", icon: `<i class="ri-discord-fill ri-lg"></i>`, f: (add: boolean) => { discord.onclick(); }},
|
||||
{name: "telegram", icon: `<i class="ri-telegram-fill ri-lg"></i>`, f: (add: boolean) => { telegram.onclick() }},
|
||||
{name: "matrix", icon: `<span class="font-bold">[m]</span>`, f: null}
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user