Skip to content

Commit

Permalink
Remove Backbone (Skeletor) router
Browse files Browse the repository at this point in the history
Use the builtin History API and event listeners.
  • Loading branch information
jcbrand committed Aug 7, 2023
1 parent 1cbb5cc commit 45f36b8
Show file tree
Hide file tree
Showing 20 changed files with 77 additions and 46 deletions.
3 changes: 2 additions & 1 deletion src/headless/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import './shared/constants.js';
import advancedFormat from 'dayjs/plugin/advancedFormat';
import api from './shared/api/index.js';
import u from './utils/core.js';
import _converse from './shared/_converse';
import dayjs from 'dayjs';
import i18n from './shared/i18n';
Expand Down Expand Up @@ -35,6 +36,6 @@ import "./plugins/vcard/index.js"; // XEP-0054 VCard-temp

import log from './log.js';

export { api, converse, _converse, i18n, log };
export { api, converse, _converse, i18n, log, u };

export default converse;
4 changes: 2 additions & 2 deletions src/headless/log.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isElement } from './utils/core.js';

const LEVELS = {
export const LEVELS = {
'debug': 0,
'info': 1,
'warn': 2,
Expand All @@ -27,7 +27,7 @@ export default {
/**
* The the log-level, which determines how verbose the logging is.
* @method log#setLogLevel
* @param { number } level - The loglevel which allows for filtering of log messages
* @param {keyof LEVELS} level - The loglevel which allows for filtering of log messages
*/
setLogLevel (level) {
if (!['debug', 'info', 'warn', 'error', 'fatal'].includes(level)) {
Expand Down
7 changes: 4 additions & 3 deletions src/headless/plugins/chat/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import ChatBox from './model.js';
import Message from './message.js';
import Messages from './messages.js';
import chat_api from './api.js';
import { _converse, api, converse } from '../../index.js';
import { _converse, api, converse, u } from '../../index.js';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import u.
import {
autoJoinChats,
enableCarbons,
handleMessageStanza,
onClearSession,
openChat,
routeToChat,
registerMessageHandlers,
} from './utils.js';

Expand Down Expand Up @@ -45,7 +45,8 @@ converse.plugins.add('converse-chat', {
ChatBox
);

_converse.router.route('converse/chat?jid=:jid', openChat);
routeToChat();
addEventListener('hashchange', routeToChat);

api.listen.on('chatBoxesFetched', autoJoinChats);
api.listen.on('presencesInitialized', registerMessageHandlers);
Expand Down
7 changes: 6 additions & 1 deletion src/headless/plugins/chat/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import { shouldClearCache } from '@converse/headless/utils/core.js';

const { Strophe, u } = converse.env;

export function openChat (jid) {
export function routeToChat (event) {
if (!location.hash.startsWith('#converse/chat?jid=')) {
return;
}
event?.preventDefault();
const jid = location.hash.split('=').pop();
if (!u.isValidJID(jid)) {
return log.warn(`Invalid JID "${jid}" provided in URL fragment`);
}
Expand Down
5 changes: 3 additions & 2 deletions src/headless/plugins/muc/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import ChatRoomOccupant from './occupant.js';
import ChatRoomOccupants from './occupants.js';
import affiliations_api from './affiliations/api.js';
import muc_api from './api.js';
import { _converse, api, converse } from '../../index.js';
import { _converse, api, converse, u } from '../../index.js';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import u.
import {
autoJoinRooms,
disconnectChatRooms,
Expand Down Expand Up @@ -178,7 +178,8 @@ converse.plugins.add('converse-muc', {
},
};

_converse.router.route('converse/room?jid=:jid', routeToRoom);
routeToRoom();
addEventListener('hashchange', routeToRoom);

_converse.ChatRoom = MUC;
_converse.ChatRoomMessage = MUCMessage;
Expand Down
10 changes: 9 additions & 1 deletion src/headless/plugins/muc/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,15 @@ export async function onWindowStateChanged (data) {
}
}

export async function routeToRoom (jid) {
/**
* @param {Event} [event]
*/
export async function routeToRoom (event) {
if (!location.hash.startsWith('#converse/room?jid=')) {
return;
}
event?.preventDefault();
const jid = location.hash.split('=').pop();
if (!u.isValidMUCJID(jid)) {
return log.warn(`invalid jid "${jid}" provided in url fragment`);
}
Expand Down
2 changes: 0 additions & 2 deletions src/headless/shared/_converse.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import i18n from './i18n.js';
import log from '../log.js';
import pluggable from 'pluggable.js/src/pluggable.js';
import { Events } from '@converse/skeletor/src/events.js';
import { Router } from '@converse/skeletor/src/router.js';
import { createStore, getDefaultStore } from '../utils/storage.js';
import { getInitSettings } from './settings/utils.js';
import { getOpenPromise } from '@converse/openpromise';
Expand Down Expand Up @@ -84,7 +83,6 @@ const _converse = {
},

default_connection_options: {'explicitResourceBinding': true},
router: new Router(),

isTestEnv: () => {
return getInitSettings()['bosh_service_url'] === 'montague.lit/http-bind';
Expand Down
18 changes: 6 additions & 12 deletions src/headless/shared/api/public.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import dayjs from 'dayjs';
import i18n from '../i18n';
import log from '../../log.js';
import sizzle from 'sizzle';
import u, { setUnloadEvent } from '../../utils/core.js';
import u, { setUnloadEvent, setLogLevelFromRoute } from '../../utils/core.js';
import { ANONYMOUS, CHAT_STATES, KEYCODES, VERSION_NAME } from '../constants.js';
import { Collection } from "@converse/skeletor/src/collection";
import { Model } from '@converse/skeletor/src/model.js';
Expand Down Expand Up @@ -50,7 +50,7 @@ export const converse = Object.assign(window.converse || {}, {
* @async
* @memberOf converse
* @method initialize
* @param { object } config A map of [configuration-settings](https://conversejs.org/docs/html/configuration.html#configuration-settings).
* @param { object } settings A map of [configuration-settings](https://conversejs.org/docs/html/configuration.html#configuration-settings).
* @example
* converse.initialize({
* auto_list_rooms: false,
Expand Down Expand Up @@ -80,10 +80,10 @@ export const converse = Object.assign(window.converse || {}, {
"authentication with auto_login.");
}
}
_converse.router.route(
/^converse\?loglevel=(debug|info|warn|error|fatal)$/, 'loglevel',
l => log.setLogLevel(l)
);

setLogLevelFromRoute();
addEventListener('hashchange', setLogLevelFromRoute);

_converse.connfeedback = new ConnectionFeedback();

/* When reloading the page:
Expand All @@ -107,12 +107,6 @@ export const converse = Object.assign(window.converse || {}, {

registerGlobalEventHandlers(_converse);

try {
!History.started && _converse.router.history.start();
} catch (e) {
log.error(e);
}

const plugins = _converse.pluggable.plugins
if (api.settings.get("auto_login") || api.settings.get("keepalive") && plugins['converse-bosh']?.enabled()) {
await api.user.login(null, null, true);
Expand Down
18 changes: 17 additions & 1 deletion src/headless/utils/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
import DOMPurify from 'dompurify';
import _converse from '@converse/headless/shared/_converse.js';
import log from '../log.js';
import log, { LEVELS } from '../log.js';
import sizzle from "sizzle";
import { Model } from '@converse/skeletor/src/model.js';
import { Strophe } from 'strophe.js';
Expand Down Expand Up @@ -55,6 +55,22 @@ const u = {
webForm2xForm,
};


/**
* @param {Event} [event]
*/
export function setLogLevelFromRoute (event) {
if (location.hash.startsWith('#converse?loglevel=')) {
event?.preventDefault();
const level = location.hash.split('=').pop();
if (Object.keys(LEVELS).includes(level)) {
log.setLogLevel(/** @type {keyof LEVELS} */(level));
} else {
log.error(`Could not set loglevel of ${level}`);
}
}
}

export function isElement (el) {
return el instanceof Element || el instanceof HTMLDocument;
}
Expand Down
1 change: 0 additions & 1 deletion src/headless/utils/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,6 @@ function unregisterGlobalEventHandlers (_converse) {
export async function cleanup (_converse) {
const { api } = _converse;
await api.trigger('cleanup', {'synchronous': true});
_converse.router.history.stop();
unregisterGlobalEventHandlers(_converse);
_converse.connection?.reset();
_converse.stopListening();
Expand Down
1 change: 0 additions & 1 deletion src/plugins/adhoc-views/tests/adhoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ describe("Ad-hoc commands consisting of multiple steps", function () {
`));

let button = await u.waitUntil(() => modal.querySelector('input[data-action="next"]'));
debugger;
button.click();

sel = `iq[to="${entity_jid}"] command[sessionid="${sessionid}"]`;
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/chatview/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { __ } from 'i18n';
import { _converse, api } from '@converse/headless';

export function clearHistory (jid) {
if (_converse.router.history.getFragment() === `converse/chat?jid=${jid}`) {
_converse.router.navigate('');
if (location.hash === `converse/chat?jid=${jid}`) {
history.pushState(null, '', window.location.pathname);
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/plugins/controlbox/loginform.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,9 @@ class LoginForm extends CustomElement {
});
}

// eslint-disable-next-line class-methods-use-this
connect (jid) {
if (['converse/login', 'converse/register'].includes(_converse.router.history.getFragment())) {
_converse.router.navigate('', { 'replace': true });
if (['converse/login', 'converse/register'].includes(location.hash)) {
history.pushState(null, '', window.location.pathname);
}
_converse.connection?.reset();
api.user.login(jid);
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/headlines-view/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class HeadlinesFeedView extends BaseChatView {

async close (ev) {
ev?.preventDefault?.();
if (_converse.router.history.getFragment() === 'converse/chat?jid=' + this.model.get('jid')) {
_converse.router.navigate('');
if (location.hash === 'converse/chat?jid=' + this.model.get('jid')) {
history.pushState(null, '', window.location.pathname);
}
await this.model.close(ev);
return this;
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/mam-views/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export async function fetchMessagesOnScrollUp (view) {
return;
}
if (api.settings.get('allow_url_history_change')) {
_converse.router.history.navigate(`#${oldest_message.get('msgid')}`);
history.pushState(null, '', `#${oldest_message.get('msgid')}`)

Check notice

Code scanning / CodeQL

Semicolon insertion Note

Avoid automated semicolon insertion (92% of all statements in
the enclosing function
have an explicit semicolon).
}
setTimeout(() => view.model.ui.set('chat-content-spinner-top', false), 250);
}
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/muc-views/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export function confirmDirectMUCInvitation ({ contact, jid, reason }) {
}

export function clearHistory (jid) {
if (_converse.router.history.getFragment() === `converse/room?jid=${jid}`) {
_converse.router.navigate('');
if (location.hash === `converse/room?jid=${jid}`) {
history.pushState(null, '', window.location.pathname);
}
}

Expand Down
10 changes: 4 additions & 6 deletions src/plugins/register/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
*/
import './panel.js';
import { __ } from 'i18n';
import { _converse, api, converse } from '@converse/headless';
import { setActiveForm } from './utils.js';
import { api, converse } from '@converse/headless';
import { routeToForm } from './utils.js';
import { CONNECTION_STATUS } from '@converse/headless/shared/constants';

// Strophe methods for building stanzas
Expand All @@ -34,8 +34,6 @@ converse.plugins.add('converse-register', {
},

initialize () {
const { router } = _converse;

CONNECTION_STATUS[Strophe.Status.REGIFAIL] = 'REGIFAIL';
CONNECTION_STATUS[Strophe.Status.REGISTERED] = 'REGISTERED';
CONNECTION_STATUS[Strophe.Status.CONFLICT] = 'CONFLICT';
Expand All @@ -48,7 +46,7 @@ converse.plugins.add('converse-register', {
'registration_domain': ''
});

router.route('converse/login', () => setActiveForm('login'));
router.route('converse/register', () => setActiveForm('register'));
routeToForm();
addEventListener('hashchange', routeToForm);
}
});
4 changes: 2 additions & 2 deletions src/plugins/register/panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ class RegisterPanel extends CustomElement {
log.debug("Registered successfully.");
_converse.connection.reset();

if (["converse/login", "converse/register"].includes(_converse.router.history.getFragment())) {
_converse.router.navigate('', {'replace': true});
if (["converse/login", "converse/register"].includes(window.location.hash)) {
history.pushState(null, '', window.location.pathname);
}
setActiveForm('login');

Expand Down
10 changes: 10 additions & 0 deletions src/plugins/register/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@ export async function setActiveForm (value) {
const controlbox = _converse.chatboxes.get('controlbox');
controlbox.set({ 'active-form': value });
}

export function routeToForm (event) {
if (location.hash === '#converse/login') {
event?.preventDefault();
setActiveForm('login');
} else if (location.hash === '#converse/register') {
event?.preventDefault();
setActiveForm('register');
}
}
4 changes: 3 additions & 1 deletion src/shared/chat/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ export function onScrolledDown (model) {
if (api.settings.get('allow_url_history_change')) {
// Clear location hash if set to one of the messages in our history
const hash = window.location.hash;
hash && model.messages.get(hash.slice(1)) && _converse.router.history.navigate();
if (hash && model.messages.get(hash.slice(1))) {
history.pushState(null, '', window.location.pathname);
}
}
}
}
Expand Down

0 comments on commit 45f36b8

Please sign in to comment.