diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..bad8e8e
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+src/discord.js/**
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 239340b..4ab68ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,5 @@ moc/
**/*.js
!**/*.util.js
node_modules/
-!src/ui/client.js
*.autosave
Makefile
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index deb1d98..3e9f5f6 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -2,7 +2,7 @@
"files.exclude": {
"**/*.cache": true,
"**/*.inf": true,
- "**/*.js": true,
+ "src/js/**/*.js": true,
"**/*.loc": true,
"**/*.mmp": true,
"**/*.pkg": true,
diff --git a/src/globals.d.ts b/src/globals.d.ts
index e8b361b..303ea7b 100644
--- a/src/globals.d.ts
+++ b/src/globals.d.ts
@@ -116,6 +116,7 @@ declare namespace Qml {
}
interface PageStackWindow extends Window {
+ initialPage: Qml.Page
pageStack: PageStack
}
@@ -174,17 +175,15 @@ declare function openDatabaseSync(
callback?: (db: Qt.Database) => void
): Database;
-declare interface Window extends Qml.PageStackWindow {
+declare interface Window extends Qml.Component, Qml.PageStackWindow {
+ client: import("./js/client/Client").Client
+ store: import("./js/store/DatabaseStore").DatabaseStore
}
const avkon: AvkonHelper;
const socket: Socket;
const http: HttpClient;
const viewer: QmlApplicationViewer;
-const global: Qml.Component & {
- client: import("./js/client/Client").Client
- store: import("./js/store/DatabaseStore").DatabaseStore
-};
const ListView: {
Beginning: number
diff --git a/src/js/client/http/Http.ts b/src/js/client/http/Http.ts
index cab938c..5a6795d 100644
--- a/src/js/client/http/Http.ts
+++ b/src/js/client/http/Http.ts
@@ -12,7 +12,7 @@ export const Http = {
) {
const METHOD = method.toUpperCase();
- http.request(METHOD, path, global.store.get("settings").token, body ?? "");
+ http.request(METHOD, path, window.store.get("settings").token, body ?? "");
function listener(response: string) {
callback(null, JSON.parse(response));
diff --git a/src/js/client/socket/SocketManager.ts b/src/js/client/socket/SocketManager.ts
index 55753e3..6a6aa0b 100644
--- a/src/js/client/socket/SocketManager.ts
+++ b/src/js/client/socket/SocketManager.ts
@@ -10,7 +10,7 @@ export class SocketManager {
constructor(private client: Client) { }
connect() {
- const settings = global.store.get("settings");
+ const settings = window.store.get("settings");
const [host, port] = (settings.proxyUrl || defaultSettings.proxyUrl).split(":");
socket.connectToServer(host, +port);
diff --git a/src/js/ui/DMPage/DMPage.qml b/src/js/ui/DMPage/DMPage.qml
index 351b15c..b539810 100644
--- a/src/js/ui/DMPage/DMPage.qml
+++ b/src/js/ui/DMPage/DMPage.qml
@@ -7,6 +7,8 @@ Page {
property string pageName: "Direct Messages"
+ tools: toolbar
+
Component.onCompleted: Js.handleReady()
SystemPalette { id: palette; colorGroup: SystemPalette.Active }
diff --git a/src/js/ui/DMPage/DMPage.ts b/src/js/ui/DMPage/DMPage.ts
index 73c710c..59d3884 100644
--- a/src/js/ui/DMPage/DMPage.ts
+++ b/src/js/ui/DMPage/DMPage.ts
@@ -14,19 +14,19 @@ declare const dmPage: Qml.Page & Qml.Component;
function loadChannels() {
dmListModel.clear();
- const cdnProxyUrl = global.store.get("settings").cdnProxyUrl || defaultSettings.cdnProxyUrl;
- const channels = Object.keys(global.client.privateChannels)
- .filter(a => global.client.privateChannels[a].lastMessageId)
+ const cdnProxyUrl = window.store.get("settings").cdnProxyUrl || defaultSettings.cdnProxyUrl;
+ const channels = Object.keys(window.client.privateChannels)
+ .filter(a => window.client.privateChannels[a].lastMessageId)
.sort((a, b) => {
- const ac = global.client.privateChannels[a];
- const bc = global.client.privateChannels[b];
+ const ac = window.client.privateChannels[a];
+ const bc = window.client.privateChannels[b];
return ac.lastMessageId.localeCompare(bc.lastMessageId);
}).reverse();
channels.length = 50;
channels.forEach(channelId => {
- const channel: PrivateChannel = global.client.privateChannels[channelId];
+ const channel: PrivateChannel = window.client.privateChannels[channelId];
const [recipient] = channel.recipients;
const item = {
id: channelId,
@@ -42,7 +42,7 @@ function loadChannels() {
function handleReady() {
setTimeout(() => {
- global.client.on("ready", loadChannels);
+ window.client.on("ready", loadChannels);
});
}
@@ -51,7 +51,7 @@ function openMessages(channelId: string) {
Qt.resolvedUrl("../MessagesPage/MessagesPage.qml"),
{
channelId,
- channelName: "@" + global.client.privateChannels[channelId].recipients[0].username,
+ channelName: "@" + window.client.privateChannels[channelId].recipients[0].username,
}
);
}
\ No newline at end of file
diff --git a/src/js/ui/DMPage/GuildPage.qml b/src/js/ui/DMPage/GuildPage.qml
deleted file mode 100644
index 2fa233f..0000000
--- a/src/js/ui/DMPage/GuildPage.qml
+++ /dev/null
@@ -1,10 +0,0 @@
-import QtQuick 1.1
-import com.nokia.symbian 1.1
-import "GuildPage.js" as Js
-
-Page {
- id: guildPage
- property string guildId;
- property string guildName;
- property string pageName: guildName;
-}
\ No newline at end of file
diff --git a/src/js/ui/GuildPage/GuildPage.qml b/src/js/ui/GuildPage/GuildPage.qml
new file mode 100644
index 0000000..d7c2d2e
--- /dev/null
+++ b/src/js/ui/GuildPage/GuildPage.qml
@@ -0,0 +1,31 @@
+import QtQuick 1.1
+import com.nokia.symbian 1.1
+import "GuildPage.js" as Js
+
+PageStackWindow {
+ id: window
+ platformSoftwareInputPanelEnabled: true
+ platformInverted: false
+ showStatusBar: true
+ showToolBar: true
+
+ Component.onCompleted: Js.handleReady()
+
+ Menu {
+ id: menu
+ content: MenuLayout {
+ MenuItem {
+ id: loginButton
+ text: "Sign in"
+ }
+ MenuItem {
+ id: settingsButton
+ text: "Settings"
+ }
+ MenuItem {
+ id: backButton
+ text: "Exit"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/js/ui/GuildPage/GuildPage.ts b/src/js/ui/GuildPage/GuildPage.ts
index e69de29..e93deb8 100644
--- a/src/js/ui/GuildPage/GuildPage.ts
+++ b/src/js/ui/GuildPage/GuildPage.ts
@@ -0,0 +1,3 @@
+import { Client } from "client/Client";
+
+const client = new Client();
\ No newline at end of file
diff --git a/src/js/ui/MessagesPage/MessagesPage.ts b/src/js/ui/MessagesPage/MessagesPage.ts
index 7462515..877f200 100644
--- a/src/js/ui/MessagesPage/MessagesPage.ts
+++ b/src/js/ui/MessagesPage/MessagesPage.ts
@@ -22,7 +22,7 @@ function sendMessage(content: string) {
}
function appendMessage(msg: MessageDto) {
- const cdnProxyUrl = global.store.get("settings").cdnProxyUrl || defaultSettings.cdnProxyUrl;
+ const cdnProxyUrl = window.store.get("settings").cdnProxyUrl || defaultSettings.cdnProxyUrl;
const splitTimestamp = msg.timestamp.split("T");
const [year, month, day] = splitTimestamp[0].split("-");
const [hour, minute, second] = splitTimestamp[1].split(".")[0].split(":");
@@ -72,7 +72,7 @@ function handleMessage(msg: MessageDto) {
function handleReady() {
setTimeout(() => {
loadMessages();
- global.client.on("message", handleMessage);
+ window.client.on("message", handleMessage);
});
inputField.implicitHeightChanged.connect(() => {
@@ -103,5 +103,5 @@ function handleMessageReady(attachments: string) {
}
function handleDestroyed() {
- global.client.off("message", handleMessage);
+ window.client.off("message", handleMessage);
}
\ No newline at end of file
diff --git a/src/js/ui/SettingsPage/SettingsPage.ts b/src/js/ui/SettingsPage/SettingsPage.ts
index f0531d4..2eee895 100644
--- a/src/js/ui/SettingsPage/SettingsPage.ts
+++ b/src/js/ui/SettingsPage/SettingsPage.ts
@@ -8,7 +8,7 @@ declare const dialogField: Qml.TextField;
declare const debugModeItem: Qml.SelectionListItem;
function loadSettings() {
- const settings = global.store.get("settings");
+ const settings = window.store.get("settings");
debugModeItem.subTitle = settings.debug ? "Enabled" : "Disabled";
}
@@ -18,10 +18,10 @@ function handleReady() {
dialog.buttonClicked.connect(bi => {
if (bi === 0) {
- global.store.fetch("settings", settings => {
+ window.store.fetch("settings", settings => {
// @ts-ignore
settings[property] = dialogField.text;
- global.store.set("settings", settings);
+ window.store.set("settings", settings);
loadSettings();
});
}
@@ -29,7 +29,7 @@ function handleReady() {
tokenItem.clicked.connect(() => {
dialog.titleText = "Token";
- dialogField.text = global.store.get("settings").token ?? "";
+ dialogField.text = window.store.get("settings").token ?? "";
dialogField.placeholderText = "";
property = "token";
dialog.open();
@@ -37,7 +37,7 @@ function handleReady() {
cdnProxyUrlItem.clicked.connect(() => {
dialog.titleText = "CDN proxy URL";
- dialogField.text = global.store.get("settings").cdnProxyUrl ?? "";
+ dialogField.text = window.store.get("settings").cdnProxyUrl ?? "";
dialogField.placeholderText = "hostname:port";
property = "cdnProxyUrl";
dialog.open();
@@ -45,16 +45,16 @@ function handleReady() {
proxyUrlItem.clicked.connect(() => {
dialog.titleText = "Gateway proxy URL";
- dialogField.text = global.store.get("settings").proxyUrl ?? "";
+ dialogField.text = window.store.get("settings").proxyUrl ?? "";
dialogField.placeholderText = "hostname:port";
property = "proxyUrl";
dialog.open();
});
debugModeItem.clicked.connect(() => {
- global.store.fetch("settings", settings => {
+ window.store.fetch("settings", settings => {
settings.debug = !settings.debug;
- global.store.set("settings", settings);
+ window.store.set("settings", settings);
loadSettings();
});
});
diff --git a/src/js/ui/launcher.qml b/src/js/ui/launcher.qml
index 174d6cf..0f96ff9 100644
--- a/src/js/ui/launcher.qml
+++ b/src/js/ui/launcher.qml
@@ -1,11 +1,96 @@
import QtQuick 1.1
+import QtMobility.feedback 1.1
+import com.nokia.symbian 1.1
+import com.nokia.extras 1.1
+import "DMPage"
import "./launcher.js" as Js
-Item {
- id: global
+PageStackWindow {
+ id: window
+ platformSoftwareInputPanelEnabled: true
+ platformInverted: false
+ showStatusBar: true
+ showToolBar: true
Component.onCompleted: Js.handleReady()
+ HapticsEffect {
+ id: hapticsEffect;
+ attackTime: 250;
+ fadeTime: 250;
+ attackIntensity: 0;
+ fadeIntensity: 0
+ }
+
+ InfoBanner {
+ id: banner
+ }
+
+ Menu {
+ id: menu
+ content: MenuLayout {
+ MenuItem {
+ id: loginButton
+ text: "Sign in"
+ }
+ MenuItem {
+ id: settingsButton
+ text: "Settings"
+ }
+ MenuItem {
+ id: backButton
+ text: "Exit"
+ }
+ }
+ }
+
+ ToolBarLayout {
+ id: toolbar
+
+ ToolButton {
+ id: minimizeButton
+ flat: true
+ iconSource: "toolbar-back"
+ }
+
+ ToolButton {
+ id: menuButton
+ iconSource: "toolbar-menu"
+ }
+ }
+
+ StatusBar {
+ y: -window.y
+ Item {
+ anchors { left: parent.left; leftMargin: 6; bottom: parent.bottom; top: parent.top }
+ width: parent.width - 186;
+ clip: true
+ Text {
+ id: statusBarText
+ anchors.verticalCenter: parent.verticalCenter
+ maximumLineCount: 1
+ color: "white"
+ font.pointSize: 6
+ font.bold: true
+ }
+ Rectangle {
+ width: 25
+ anchors { top: parent.top; bottom: parent.bottom; right: parent.right }
+ rotation: -90
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#00000000" }
+ GradientStop { position: 1.0; color: "#ff000000" }
+ }
+ }
+ }
+ Connections {
+ target: pageStack
+ onCurrentPageChanged: statusBarText.text = pageStack.currentPage.pageName
+ }
+ }
+
+ function module() {}
+
function exports() {}
function require(url) {
@@ -13,7 +98,7 @@ Item {
}
function setTimeout(callback, timeout) {
- const timer = Qt.createQmlObject("import QtQuick 1.0; Timer {}", global);
+ const timer = Qt.createQmlObject("import QtQuick 1.0; Timer {}", window);
timer.interval = timeout || 1;
timer.repeat = false;
@@ -33,7 +118,7 @@ Item {
}
function setInterval(callback, timeout) {
- const timer = Qt.createQmlObject("import QtQuick 1.0; Timer {}", global);
+ const timer = Qt.createQmlObject("import QtQuick 1.0; Timer {}", window);
timer.interval = timeout || 1;
timer.repeat = true;
diff --git a/src/js/ui/launcher.ts b/src/js/ui/launcher.ts
index e3f84dc..ddebb88 100644
--- a/src/js/ui/launcher.ts
+++ b/src/js/ui/launcher.ts
@@ -1,11 +1,14 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
-declare const exports: any;
+declare let module: any;
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+declare let exports: any;
const timers: string[] = [];
const directories = [
"",
+ "../",
"ui/",
"ui/DMPage/",
"utils/",
@@ -17,18 +20,54 @@ const directories = [
"structures/",
"structures/dto/",
"structures/dto/events/",
+ "../discord.js/",
+ "../discord.js/client/",
+ "../discord.js/sharding/",
+ "../discord.js/structures/",
+ "../discord.js/util/",
] as const;
function require(url: string) {
for (const dir of directories) {
- if(Qt.include("../" + dir + url + ".js").status === 0) {
+ const modulePath = "../" + dir + url + ".js";
+ const result = Qt.include(modulePath);
+
+ if(result.status === 0) {
+ console.log(`Loaded module "${modulePath}"`);
+
+ return exports;
+ } else if (result.status !== 2) {
+ // @ts-ignore
+ console.log(`Could not load module "${modulePath}", error code ${result.status}. ${result.exception}`);
+ }
+ }
+
+ for (const dir of directories) {
+ const modulePath = "../" + dir + url + "/index.js";
+ const result = Qt.include(modulePath);
+
+ if(result.status === 0) {
+ console.log(`Loaded module "${modulePath}"`);
+
return exports;
+ } else if (result.status !== 2) {
+ // @ts-ignore
+ console.log(`Could not load module "${modulePath}", error code ${result.status}. ${result.exception}`);
}
}
+
+ throw new Error(`Could not load module "${url}"`);
}
function handleReady() {
+ Object.defineProperty(module, "exports", {
+ get() { return exports; },
+ set(v) {
+ exports = v;
+ },
+ });
+
const component = Qt.createComponent("main.qml");
- component.createObject(global);
+ component.createObject(window);
}
\ No newline at end of file
diff --git a/src/js/ui/main.qml b/src/js/ui/main.qml
index f4defe7..c4c9e9e 100644
--- a/src/js/ui/main.qml
+++ b/src/js/ui/main.qml
@@ -1,93 +1,6 @@
import QtQuick 1.1
-import QtMobility.feedback 1.1
-import com.nokia.symbian 1.1
-import com.nokia.extras 1.1
-import "DMPage"
-import "MessagesPage"
import "main.js" as Js
-PageStackWindow {
- id: window
- platformSoftwareInputPanelEnabled: true
- platformInverted: false
- initialPage: DMPage { x: 0; y: 0; tools: toolbar; }
- showStatusBar: true
- showToolBar: true
-
+Item {
Component.onCompleted: Js.handleReady()
-
- HapticsEffect {
- id: hapticsEffect;
- attackTime: 250;
- fadeTime: 250;
- attackIntensity: 0;
- fadeIntensity: 0
- }
-
- InfoBanner {
- id: banner
- }
-
- Menu {
- id: menu
- content: MenuLayout {
- MenuItem {
- id: loginButton
- text: "Sign in"
- }
- MenuItem {
- id: settingsButton
- text: "Settings"
- }
- MenuItem {
- id: backButton
- text: "Exit"
- }
- }
- }
-
- ToolBarLayout {
- id: toolbar
-
- ToolButton {
- id: minimizeButton
- flat: true
- iconSource: "toolbar-back"
- }
-
- ToolButton {
- id: menuButton
- iconSource: "toolbar-menu"
- }
- }
-
- StatusBar {
- y: -window.y
- Item {
- anchors { left: parent.left; leftMargin: 6; bottom: parent.bottom; top: parent.top }
- width: parent.width - 186;
- clip: true
- Text {
- id: statusBarText
- anchors.verticalCenter: parent.verticalCenter
- maximumLineCount: 1
- color: "white"
- font.pointSize: 6
- font.bold: true
- }
- Rectangle {
- width: 25
- anchors { top: parent.top; bottom: parent.bottom; right: parent.right }
- rotation: -90
- gradient: Gradient {
- GradientStop { position: 0.0; color: "#00000000" }
- GradientStop { position: 1.0; color: "#ff000000" }
- }
- }
- }
- Connections {
- target: pageStack
- onCurrentPageChanged: statusBarText.text = pageStack.currentPage.pageName
- }
- }
}
diff --git a/src/js/ui/main.ts b/src/js/ui/main.ts
index b6a692d..aa46413 100644
--- a/src/js/ui/main.ts
+++ b/src/js/ui/main.ts
@@ -12,11 +12,11 @@ declare const symbian: Qml.Symbian;
declare const hapticsEffect: Qml.HapticsEffect;
function loadGlobalScope() {
- Object.defineProperty(global, "client", {
+ Object.defineProperty(window, "client", {
value: new Client(),
});
- Object.defineProperty(global, "store", {
+ Object.defineProperty(window, "store", {
value: new DatabaseStore(),
});
}
@@ -26,7 +26,7 @@ function handleReady() {
symbian.foregroundChanged.connect(() => {
console.log(symbian.foreground);
- global.client.setBackground(!symbian.foreground);
+ window.client.setBackground(!symbian.foreground);
});
backButton.clicked.connect(() => {
@@ -34,10 +34,10 @@ function handleReady() {
});
loginButton.clicked.connect(() => {
- const settings = global.store.get("settings");
+ const settings = window.store.get("settings");
if (settings.token) {
- global.client.login(settings.token);
+ window.client.login(settings.token);
} else {
banner.text = "You need to provide a token in order to sign in.";
banner.open();
@@ -58,19 +58,19 @@ function handleReady() {
avkon.minimize();
});
- global.client.on("ready", () => {
+ window.client.on("ready", () => {
console.log("Connected to Discord.");
});
- global.client.on("debug", msg => {
- if (global.store.get("settings").debug) {
+ window.client.on("debug", msg => {
+ if (window.store.get("settings").debug) {
console.log("[Socket DEBUG]", msg);
}
});
- global.client.on("message", msg => {
- if (msg.author.id !== global.client.user!.id
- && (!msg.guild_id || msg.mentions.some(m => m.id === global.client.user!.id))
+ window.client.on("message", msg => {
+ if (msg.author.id !== window.client.user!.id
+ && (!msg.guild_id || msg.mentions.some(m => m.id === window.client.user!.id))
) {
if (symbian.foreground) {
banner.text = `${msg.author.username}
${msg.content}`;
@@ -85,5 +85,11 @@ function handleReady() {
}
});
- global.client.ready();
-}
+ window.client.ready();
+
+ const dmPage = Qt.createComponent("./DMPage/DMPage.qml") as Qml.Page;
+
+ dmPage.createObject(window);
+
+ window.initialPage = dmPage;
+}
\ No newline at end of file