login page is displayed now
This commit is contained in:
+1
-28
@@ -28,38 +28,11 @@
|
|||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
||||||
<!-- Styles for local elements -->
|
<!-- Styles for local elements -->
|
||||||
<link rel="stylesheet" href="css/base.css" />
|
<link rel="stylesheet" href="css/base.css" />
|
||||||
<!-- ReactJs scripts -->
|
|
||||||
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
|
|
||||||
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
|
|
||||||
<script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
|
||||||
<!-- Localization support -->
|
|
||||||
<script crossorigin src="https://unpkg.com/prop-types@15/prop-types.js"></script>
|
|
||||||
<script crossorigin src="https://unpkg.com/react-intl@2/dist/react-intl.js"></script>
|
|
||||||
<script>
|
|
||||||
// Extract react-intl objects
|
|
||||||
var {IntlProvider, FormattedMessage} = ReactIntl;
|
|
||||||
</script>
|
|
||||||
<!-- Firebase push notifications. -->
|
|
||||||
<script crossorigin src="https://unpkg.com/firebase@5.5.5/firebase-app.js"></script>
|
|
||||||
<script crossorigin src="https://unpkg.com/firebase@5.5.5/firebase-messaging.js"></script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="mountPoint"></div>
|
<div id="mountPoint"></div>
|
||||||
<!-- core tinode libraries -->
|
|
||||||
<script src="src/drafty.js"></script>
|
|
||||||
<script src="src/tinode.js"></script>
|
|
||||||
<!-- the application -->
|
<!-- the application -->
|
||||||
<script src="/firebase-init.js"></script>
|
<script src="umd/index.dev.js"></script>
|
||||||
<script type="text/babel" src="src/index.js"></script>
|
|
||||||
<!--script type="text/babel">
|
|
||||||
ReactDOM.render(
|
|
||||||
<IntlProvider
|
|
||||||
locale={navigator.language}>
|
|
||||||
<TinodeWeb />
|
|
||||||
</IntlProvider>,
|
|
||||||
document.getElementById('mountPoint')
|
|
||||||
);
|
|
||||||
</script-->
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+3
-3
@@ -22,9 +22,9 @@
|
|||||||
"build:prod": "browserify ./src/index.js --standalone Webapp | uglifyjs --compress --mangle > ./umd/index.prod.js",
|
"build:prod": "browserify ./src/index.js --standalone Webapp | uglifyjs --compress --mangle > ./umd/index.prod.js",
|
||||||
"build:dev": "browserify ./src/index.js --standalone Webapp > ./umd/index.dev.js",
|
"build:dev": "browserify ./src/index.js --standalone Webapp > ./umd/index.dev.js",
|
||||||
"build:css": "postcss css/base.css > css/base.min.css",
|
"build:css": "postcss css/base.css > css/base.min.css",
|
||||||
"wp-build:dev": "webpack --mode development --output ./umd/index.dev.js",
|
"wp-build:dev": "webpack --mode development --output-library-target umd --output ./umd/index.dev.js",
|
||||||
"wp-build:prod": "webpack --mode production --output ./umd/index.prod.js",
|
"wp-build:prod": "webpack --mode production --output-library-target umd --output ./umd/index.prod.js",
|
||||||
"vers": "echo \"{\\\"version\\\": \\\"`node -p -e \"require('./package.json').version\"`\\\"}\" > version.json"
|
"vers": "echo \"export const PACKAGE_VERSION = \\\"`node -p -e \"require('./package.json').version\"`\\\";\" > src/version.js"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"src/index.js",
|
"src/index.js",
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
// Must be located at the root.
|
// Must be located at the root.
|
||||||
importScripts("https://unpkg.com/firebase@5.5.5/firebase-app.js");
|
importScripts("https://unpkg.com/firebase@5.5.5/firebase-app.js");
|
||||||
importScripts("https://unpkg.com/firebase@5.5.5/firebase-messaging.js");
|
importScripts("https://unpkg.com/firebase@5.5.5/firebase-messaging.js");
|
||||||
importScripts("/firebase-init.js")
|
importScripts("/src/firebase-init.js")
|
||||||
|
|
||||||
firebase.initializeApp(FIREBASE_INIT);
|
firebase.initializeApp(FIREBASE_INIT);
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -1,5 +1,7 @@
|
|||||||
|
import { PACKAGE_VERSION } from './version.js';
|
||||||
|
|
||||||
// Name of this application, used in the User-Agent.
|
// Name of this application, used in the User-Agent.
|
||||||
export const APP_NAME = 'TinodeWeb/' + (package_version || '0.15');
|
export const APP_NAME = 'TinodeWeb/' + (PACKAGE_VERSION || '0.15');
|
||||||
|
|
||||||
// API key. Use https://github.com/tinode/chat/tree/master/keygen to generate your own
|
// API key. Use https://github.com/tinode/chat/tree/master/keygen to generate your own
|
||||||
export const API_KEY = 'AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K';
|
export const API_KEY = 'AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K';
|
||||||
|
|||||||
+6
-1
@@ -3,9 +3,14 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
import { IntlProvider } from 'react-intl';
|
||||||
|
|
||||||
import TinodeWeb from './views/tinode-web.jsx';
|
import TinodeWeb from './views/tinode-web.jsx';
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
React.createElement(TinodeWeb, null),
|
<IntlProvider
|
||||||
|
locale={navigator.language}>
|
||||||
|
<TinodeWeb />
|
||||||
|
</IntlProvider>,
|
||||||
document.getElementById('mountPoint')
|
document.getElementById('mountPoint')
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {KNOWN_HOSTS, DEFAULT_HOST} from '../config.js';
|
import { KNOWN_HOSTS, DEFAULT_HOST } from '../config.js';
|
||||||
|
|
||||||
// Detect server address from the URL
|
// Detect server address from the URL
|
||||||
function detectServerAddress() {
|
export function detectServerAddress() {
|
||||||
let host = DEFAULT_HOST;
|
let host = DEFAULT_HOST;
|
||||||
if (typeof window.location == 'object') {
|
if (typeof window.location == 'object') {
|
||||||
if (window.location.protocol == 'file:' || window.location.hostname == 'localhost') {
|
if (window.location.protocol == 'file:' || window.location.hostname == 'localhost') {
|
||||||
@@ -14,14 +14,14 @@ function detectServerAddress() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Detect if the page is served over HTTPS.
|
// Detect if the page is served over HTTPS.
|
||||||
function isSecureConnection() {
|
export function isSecureConnection() {
|
||||||
if (typeof window.location == 'object') {
|
if (typeof window.location == 'object') {
|
||||||
return window.location.protocol == 'https:';
|
return window.location.protocol == 'https:';
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLocalHost() {
|
export function isLocalHost() {
|
||||||
if (typeof window.location == 'object') {
|
if (typeof window.location == 'object') {
|
||||||
return window.location.hostname == 'localhost';
|
return window.location.hostname == 'localhost';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// Helper functions for storing values in localStorage.
|
||||||
|
// By default localStorage can store only strings, not objects or other types.
|
||||||
|
|
||||||
|
export default class LocalStorageUtil {
|
||||||
|
// Replace old object with the new one.
|
||||||
|
static setObject(key, value) {
|
||||||
|
localStorage.setItem(key, JSON.stringify(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get stored object.
|
||||||
|
static getObject(key) {
|
||||||
|
let value = localStorage.getItem(key);
|
||||||
|
return value && JSON.parse(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Partially or wholly update stored object.
|
||||||
|
static updateObject(key, value) {
|
||||||
|
let oldVal = localStorage.getObject(key);
|
||||||
|
localStorage.setObject(key, Object.assign(oldVal || {}, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+57
-56
@@ -1,67 +1,68 @@
|
|||||||
// Helper functions for hash navigation.
|
// Utility class for hash navigation.
|
||||||
|
|
||||||
// Parse hash as in http://www.example.com/path#hash as if it were
|
// Parse hash as in http://www.example.com/path#hash as if it were
|
||||||
// path and arguments.
|
// path and arguments.
|
||||||
export function parseUrlHash(hash) {
|
export default class HashNavigation {
|
||||||
// Split path from args, path -> parts[0], args->path[1]
|
static parseUrlHash(hash) {
|
||||||
let parts = hash.split('?', 2);
|
// Split path from args, path -> parts[0], args->path[1]
|
||||||
let params = {};
|
let parts = hash.split('?', 2);
|
||||||
let path = [];
|
let params = {};
|
||||||
if (parts[0]) {
|
let path = [];
|
||||||
path = parts[0].substr(1).split('/');
|
if (parts[0]) {
|
||||||
}
|
path = parts[0].substr(1).split('/');
|
||||||
if (parts[1]) {
|
|
||||||
parts[1].split('&').forEach(function(part) {
|
|
||||||
let item = part.split('=');
|
|
||||||
if (item[0]) {
|
|
||||||
params[decodeURIComponent(item[0])] = decodeURIComponent(item[1]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return {path: path, params: params};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function navigateTo(url) {
|
|
||||||
window.location.hash = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function composeUrlHash(path, params) {
|
|
||||||
var url = path.join('/');
|
|
||||||
var args = [];
|
|
||||||
for (var key in params) {
|
|
||||||
if (params.hasOwnProperty(key)) {
|
|
||||||
args.push(key + '=' + params[key]);
|
|
||||||
}
|
}
|
||||||
|
if (parts[1]) {
|
||||||
|
parts[1].split('&').forEach(function(part) {
|
||||||
|
let item = part.split('=');
|
||||||
|
if (item[0]) {
|
||||||
|
params[decodeURIComponent(item[0])] = decodeURIComponent(item[1]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {path: path, params: params};
|
||||||
}
|
}
|
||||||
if (args.length > 0) {
|
|
||||||
url += '?' + args.join('&');
|
static navigateTo(url) {
|
||||||
|
window.location.hash = url;
|
||||||
}
|
}
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addUrlParam(hash, key, value) {
|
static composeUrlHash(path, params) {
|
||||||
var parsed = parseUrlHash(hash);
|
var url = path.join('/');
|
||||||
parsed.params[key] = value;
|
var args = [];
|
||||||
return composeUrlHash(parsed.path, parsed.params);
|
for (var key in params) {
|
||||||
}
|
if (params.hasOwnProperty(key)) {
|
||||||
|
args.push(key + '=' + params[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args.length > 0) {
|
||||||
|
url += '?' + args.join('&');
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
export function removeUrlParam(hash, key) {
|
static addUrlParam(hash, key, value) {
|
||||||
var parsed = parseUrlHash(hash);
|
var parsed = parseUrlHash(hash);
|
||||||
delete parsed.params[key];
|
parsed.params[key] = value;
|
||||||
return composeUrlHash(parsed.path, parsed.params);
|
return composeUrlHash(parsed.path, parsed.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setUrlSidePanel(hash, sidepanel) {
|
static removeUrlParam(hash, key) {
|
||||||
var parsed = parseUrlHash(hash);
|
var parsed = parseUrlHash(hash);
|
||||||
parsed.path[0] = sidepanel;
|
delete parsed.params[key];
|
||||||
return composeUrlHash(parsed.path, parsed.params);
|
return composeUrlHash(parsed.path, parsed.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setUrlTopic(hash, topic) {
|
static setUrlSidePanel(hash, sidepanel) {
|
||||||
var parsed = parseUrlHash(hash);
|
var parsed = parseUrlHash(hash);
|
||||||
parsed.path[1] = topic;
|
parsed.path[0] = sidepanel;
|
||||||
// Close InfoView on topic change.
|
return composeUrlHash(parsed.path, parsed.params);
|
||||||
delete parsed.params.info;
|
}
|
||||||
return composeUrlHash(parsed.path, parsed.params);
|
|
||||||
|
static setUrlTopic(hash, topic) {
|
||||||
|
var parsed = parseUrlHash(hash);
|
||||||
|
parsed.path[1] = topic;
|
||||||
|
// Close InfoView on topic change.
|
||||||
|
delete parsed.params.info;
|
||||||
|
return composeUrlHash(parsed.path, parsed.params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// END of hash navigation helper functions
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Short representation of time in the past.
|
// Short representation of time in the past.
|
||||||
function shortDateFormat(then) {
|
export function shortDateFormat(then) {
|
||||||
var locale = window.navigator.userLanguage || window.navigator.language;
|
var locale = window.navigator.userLanguage || window.navigator.language;
|
||||||
var now = new Date();
|
var now = new Date();
|
||||||
if (then.getFullYear() == now.getFullYear()) {
|
if (then.getFullYear() == now.getFullYear()) {
|
||||||
@@ -15,7 +15,7 @@ function shortDateFormat(then) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert a number of bytes to human-readable format.
|
// Convert a number of bytes to human-readable format.
|
||||||
function bytesToHumanSize(bytes) {
|
export function bytesToHumanSize(bytes) {
|
||||||
if (!bytes || bytes == 0) {
|
if (!bytes || bytes == 0) {
|
||||||
return '0 Bytes';
|
return '0 Bytes';
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ function bytesToHumanSize(bytes) {
|
|||||||
|
|
||||||
// Get 32 bit integer hash value for a string. Ideally it should produce the same value
|
// Get 32 bit integer hash value for a string. Ideally it should produce the same value
|
||||||
// as Java's String#hash().
|
// as Java's String#hash().
|
||||||
function stringHash(value) {
|
export function stringHash(value) {
|
||||||
var hash = 0;
|
var hash = 0;
|
||||||
value = '' + value;
|
value = '' + value;
|
||||||
for (var i = 0; i < value.length; i++) {
|
for (var i = 0; i < value.length; i++) {
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
// Login form
|
// Login form
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import CheckBox from '../widgets/checkbox.jsx';
|
import CheckBox from '../widgets/checkbox.jsx';
|
||||||
import VisiblePassword from '../widgets/visible-password.jsx';
|
import VisiblePassword from '../widgets/visible-password.jsx';
|
||||||
|
|
||||||
|
import LocalStorageUtil from '../lib/local-storage.js';
|
||||||
|
|
||||||
export default class LoginView extends React.Component {
|
export default class LoginView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -14,7 +16,7 @@ export default class LoginView extends React.Component {
|
|||||||
login: props.login,
|
login: props.login,
|
||||||
password: '',
|
password: '',
|
||||||
hostName: props.serverAddress,
|
hostName: props.serverAddress,
|
||||||
saveToken: localStorage.getObject('keep-logged-in')
|
saveToken: LocalStorageUtil.getObject('keep-logged-in')
|
||||||
};
|
};
|
||||||
this.handleLoginChange = this.handleLoginChange.bind(this);
|
this.handleLoginChange = this.handleLoginChange.bind(this);
|
||||||
this.handlePasswordChange = this.handlePasswordChange.bind(this);
|
this.handlePasswordChange = this.handlePasswordChange.bind(this);
|
||||||
@@ -31,7 +33,7 @@ export default class LoginView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleToggleSaveToken() {
|
handleToggleSaveToken() {
|
||||||
localStorage.setObject('keep-logged-in', !this.state.saveToken);
|
LocalStorageUtil.setObject('keep-logged-in', !this.state.saveToken);
|
||||||
this.setState({saveToken: !this.state.saveToken});
|
this.setState({saveToken: !this.state.saveToken});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
/* This is just a static page to display when no conversation is selected. */
|
/* This is just a static page to display when no conversation is selected. */
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import Tinode from 'tinode-sdk';
|
||||||
|
|
||||||
|
import { APP_NAME } from '../config.js';
|
||||||
|
|
||||||
export default class LogoView extends React.PureComponent {
|
export default class LogoView extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
var version = APP_NAME + ' (' + Tinode.getLibrary() + ')';
|
var version = APP_NAME + ' (' + Tinode.getLibrary() + ')';
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
/* A password reset form */
|
/* A password reset form */
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import VisiblePassword from '../widgets/visible-password.jsx';
|
import VisiblePassword from '../widgets/visible-password.jsx';
|
||||||
|
|||||||
+54
-44
@@ -3,7 +3,9 @@ import React from 'react';
|
|||||||
|
|
||||||
import 'firebase/app';
|
import 'firebase/app';
|
||||||
import 'firebase/messaging';
|
import 'firebase/messaging';
|
||||||
import { FIREBASE_INIT } from '../../firebase-init.js'
|
import { FIREBASE_INIT } from '../firebase-init.js'
|
||||||
|
|
||||||
|
import Tinode from 'tinode-sdk';
|
||||||
|
|
||||||
import ContextMenu from '../widgets/context-menu.jsx';
|
import ContextMenu from '../widgets/context-menu.jsx';
|
||||||
|
|
||||||
@@ -11,6 +13,11 @@ import InfoView from './info-view.jsx';
|
|||||||
import MessagesView from './messages-view.jsx';
|
import MessagesView from './messages-view.jsx';
|
||||||
import SidepanelView from './sidepanel-view.jsx';
|
import SidepanelView from './sidepanel-view.jsx';
|
||||||
|
|
||||||
|
import { API_KEY, APP_NAME, MEDIA_BREAKPOINT, RECEIVED_DELAY } from '../config.js';
|
||||||
|
import { isLocalHost, isSecureConnection } from '../lib/host-name.js';
|
||||||
|
import LocalStorageUtil from '../lib/local-storage.js';
|
||||||
|
import HashNavigation from '../lib/navigation.js';
|
||||||
|
|
||||||
// Sound to play on message received.
|
// Sound to play on message received.
|
||||||
export const POP_SOUND = new Audio('audio/msg.mp3');
|
export const POP_SOUND = new Audio('audio/msg.mp3');
|
||||||
|
|
||||||
@@ -76,7 +83,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getBlankState() {
|
getBlankState() {
|
||||||
let settings = localStorage.getObject("settings") || {};
|
let settings = LocalStorageUtil.getObject("settings") || {};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
connected: false,
|
connected: false,
|
||||||
@@ -89,7 +96,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
desktopAlertsEnabled: (isSecureConnection() || isLocalHost()) &&
|
desktopAlertsEnabled: (isSecureConnection() || isLocalHost()) &&
|
||||||
(typeof firebase != 'undefined') && (typeof navigator != 'undefined') &&
|
(typeof firebase != 'undefined') && (typeof navigator != 'undefined') &&
|
||||||
(typeof FIREBASE_INIT != 'undefined'),
|
(typeof FIREBASE_INIT != 'undefined'),
|
||||||
firebaseToken: localStorage.getObject("firebase-token"),
|
firebaseToken: LocalStorageUtil.getObject("firebase-token"),
|
||||||
|
|
||||||
errorText: '',
|
errorText: '',
|
||||||
errorLevel: null,
|
errorLevel: null,
|
||||||
@@ -169,10 +176,10 @@ export default class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let token = localStorage.getObject('keep-logged-in') ?
|
let token = LocalStorageUtil.getObject('keep-logged-in') ?
|
||||||
localStorage.getObject('auth-token') : undefined;
|
LocalStorageUtil.getObject('auth-token') : undefined;
|
||||||
|
|
||||||
let parsedNav = parseUrlHash(window.location.hash);
|
let parsedNav = HashNavigation.parseUrlHash(window.location.hash);
|
||||||
if (token) {
|
if (token) {
|
||||||
// When reading from storage, date is returned as string.
|
// When reading from storage, date is returned as string.
|
||||||
token.expires = new Date(token.expires);
|
token.expires = new Date(token.expires);
|
||||||
@@ -184,9 +191,9 @@ export default class TinodeWeb extends React.Component {
|
|||||||
delete parsedNav.params.info;
|
delete parsedNav.params.info;
|
||||||
delete parsedNav.params.tab;
|
delete parsedNav.params.tab;
|
||||||
parsedNav.path[0] = '';
|
parsedNav.path[0] = '';
|
||||||
navigateTo(composeUrlHash(parsedNav.path, parsedNav.params));
|
HashNavigation.navigateTo(HashNavigation.composeUrlHash(parsedNav.path, parsedNav.params));
|
||||||
} else if (!parsedNav.params.token) {
|
} else if (!parsedNav.params.token) {
|
||||||
navigateTo('');
|
HashNavigation.navigateTo('');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.readTimer = null;
|
this.readTimer = null;
|
||||||
@@ -218,7 +225,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
|
|
||||||
// Handle for hashchange event: display appropriate panels.
|
// Handle for hashchange event: display appropriate panels.
|
||||||
handleHashRoute() {
|
handleHashRoute() {
|
||||||
var hash = parseUrlHash(window.location.hash);
|
var hash = HashNavigation.parseUrlHash(window.location.hash);
|
||||||
if (hash.path && hash.path.length > 0) {
|
if (hash.path && hash.path.length > 0) {
|
||||||
// Left-side panel selector.
|
// Left-side panel selector.
|
||||||
if (['register','settings','edit','cred','reset','newtpk','contacts',''].includes(hash.path[0])) {
|
if (['register','settings','edit','cred','reset','newtpk','contacts',''].includes(hash.path[0])) {
|
||||||
@@ -315,7 +322,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
doLogin(login, password, cred) {
|
doLogin(login, password, cred) {
|
||||||
if (this.tinode.isAuthenticated()) {
|
if (this.tinode.isAuthenticated()) {
|
||||||
// Already logged in. Go to default screen.
|
// Already logged in. Go to default screen.
|
||||||
navigateTo("");
|
HashNavigation.navigateTo('');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Sanitize and package credentail.
|
// Sanitize and package credentail.
|
||||||
@@ -344,30 +351,30 @@ export default class TinodeWeb extends React.Component {
|
|||||||
// Login failed, report error.
|
// Login failed, report error.
|
||||||
this.setState({loginDisabled: false, credMethod: undefined, credCode: undefined});
|
this.setState({loginDisabled: false, credMethod: undefined, credCode: undefined});
|
||||||
this.handleError(err.message, 'err');
|
this.handleError(err.message, 'err');
|
||||||
localStorage.removeItem('auth-token');
|
LocalStorageUtil.removeItem('auth-token');
|
||||||
navigateTo('');
|
HashNavigation.navigateTo('');
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// No login credentials provided.
|
// No login credentials provided.
|
||||||
// Make sure we are on the login page.
|
// Make sure we are on the login page.
|
||||||
navigateTo('');
|
HashNavigation.navigateTo('');
|
||||||
this.setState({loginDisabled: false});
|
this.setState({loginDisabled: false});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCredentialsRequest(params) {
|
handleCredentialsRequest(params) {
|
||||||
var parsed = parseUrlHash(window.location.hash);
|
var parsed = HashNavigation.parseUrlHash(window.location.hash);
|
||||||
parsed.path[0] = 'cred';
|
parsed.path[0] = 'cred';
|
||||||
parsed.params['method'] = params.cred[0];
|
parsed.params['method'] = params.cred[0];
|
||||||
navigateTo(composeUrlHash(parsed.path, parsed.params));
|
HashNavigation.navigateTo(HashNavigation.composeUrlHash(parsed.path, parsed.params));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLoginSuccessful() {
|
handleLoginSuccessful() {
|
||||||
this.handleError('', null);
|
this.handleError('', null);
|
||||||
|
|
||||||
// Refresh authentication token.
|
// Refresh authentication token.
|
||||||
if (localStorage.getObject('keep-logged-in')) {
|
if (LocalStorageUtil.getObject('keep-logged-in')) {
|
||||||
localStorage.setObject('auth-token', this.tinode.getAuthToken());
|
LocalStorageUtil.setObject('auth-token', this.tinode.getAuthToken());
|
||||||
}
|
}
|
||||||
// Logged in fine, subscribe to 'me' attaching callbacks from the contacts view.
|
// Logged in fine, subscribe to 'me' attaching callbacks from the contacts view.
|
||||||
var me = this.tinode.getMeTopic();
|
var me = this.tinode.getMeTopic();
|
||||||
@@ -387,11 +394,11 @@ export default class TinodeWeb extends React.Component {
|
|||||||
withDesc().
|
withDesc().
|
||||||
build()
|
build()
|
||||||
).catch((err) => {
|
).catch((err) => {
|
||||||
localStorage.removeItem('auth-token');
|
LocalStorageUtil.removeItem('auth-token');
|
||||||
this.handleError(err.message, 'err');
|
this.handleError(err.message, 'err');
|
||||||
navigateTo('');
|
HashNavigation.navigateTo('');
|
||||||
});
|
});
|
||||||
navigateTo(setUrlSidePanel(window.location.hash, 'contacts'));
|
HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, 'contacts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDisconnect(err) {
|
handleDisconnect(err) {
|
||||||
@@ -575,7 +582,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
topicSelectedOnline: online,
|
topicSelectedOnline: online,
|
||||||
topicSelectedAcs: acs
|
topicSelectedAcs: acs
|
||||||
});
|
});
|
||||||
navigateTo(setUrlTopic('', topicName));
|
HashNavigation.navigateTo(HashNavigation.setUrlTopic('', topicName));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Currently selected contact deleted
|
// Currently selected contact deleted
|
||||||
@@ -588,7 +595,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
showInfoPanel: false
|
showInfoPanel: false
|
||||||
});
|
});
|
||||||
if (this.state.topicSelected) {
|
if (this.state.topicSelected) {
|
||||||
navigateTo(setUrlTopic('', null));
|
HashNavigation.navigateTo(HashNavigation.setUrlTopic('', null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -598,7 +605,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
mobilePanel: 'sidepanel'
|
mobilePanel: 'sidepanel'
|
||||||
});
|
});
|
||||||
navigateTo(setUrlTopic(window.location.hash, null));
|
HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
// User is sending a message, either plain text or a drafty object, possibly
|
// User is sending a message, either plain text or a drafty object, possibly
|
||||||
@@ -631,7 +638,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
|
|
||||||
// User chose a Sign Up menu item.
|
// User chose a Sign Up menu item.
|
||||||
handleNewAccount() {
|
handleNewAccount() {
|
||||||
navigateTo(setUrlSidePanel(window.location.hash, 'register'));
|
HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, 'register'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actual registration of a new account.
|
// Actual registration of a new account.
|
||||||
@@ -673,7 +680,8 @@ export default class TinodeWeb extends React.Component {
|
|||||||
|
|
||||||
// User chose Settings menu item.
|
// User chose Settings menu item.
|
||||||
handleSettings() {
|
handleSettings() {
|
||||||
navigateTo(setUrlSidePanel(window.location.hash, this.state.myUserId ? 'edit' : 'settings'));
|
HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash,
|
||||||
|
this.state.myUserId ? 'edit' : 'settings'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// User updated global parameters.
|
// User updated global parameters.
|
||||||
@@ -692,12 +700,12 @@ export default class TinodeWeb extends React.Component {
|
|||||||
serverAddress: serverAddress,
|
serverAddress: serverAddress,
|
||||||
transport: transport
|
transport: transport
|
||||||
});
|
});
|
||||||
localStorage.setObject('settings', {
|
LocalStorageUtil.setObject('settings', {
|
||||||
serverAddress: serverAddress,
|
serverAddress: serverAddress,
|
||||||
transport: transport
|
transport: transport
|
||||||
});
|
});
|
||||||
|
|
||||||
navigateTo(setUrlSidePanel(window.location.hash, ''));
|
HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize desktop alerts = push notifications.
|
// Initialize desktop alerts = push notifications.
|
||||||
@@ -722,24 +730,24 @@ export default class TinodeWeb extends React.Component {
|
|||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
this.handleError(err.message, 'err');
|
this.handleError(err.message, 'err');
|
||||||
this.setState({desktopAlerts: false, firebaseToken: null});
|
this.setState({desktopAlerts: false, firebaseToken: null});
|
||||||
localStorage.updateObject('settings', {desktopAlerts: false});
|
LocalStorageUtil.updateObject('settings', {desktopAlerts: false});
|
||||||
console.log("Failed to get permission to notify.", err);
|
console.log("Failed to get permission to notify.", err);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({desktopAlerts: true});
|
this.setState({desktopAlerts: true});
|
||||||
localStorage.updateObject('settings', {desktopAlerts: true});
|
LocalStorageUtil.updateObject('settings', {desktopAlerts: true});
|
||||||
}
|
}
|
||||||
} else if (this.state.firebaseToken) {
|
} else if (this.state.firebaseToken) {
|
||||||
this.fbPush.deleteToken(this.state.firebaseToken).catch((err) => {
|
this.fbPush.deleteToken(this.state.firebaseToken).catch((err) => {
|
||||||
console.log("Unable to delete token.", err);
|
console.log("Unable to delete token.", err);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
localStorage.updateObject('settings', {desktopAlerts: false});
|
LocalStorageUtil.updateObject('settings', {desktopAlerts: false});
|
||||||
localStorage.removeItem('firebase-token');
|
LocalStorageUtil.removeItem('firebase-token');
|
||||||
this.setState({desktopAlerts: false, firebaseToken: null});
|
this.setState({desktopAlerts: false, firebaseToken: null});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({desktopAlerts: false, firebaseToken: null});
|
this.setState({desktopAlerts: false, firebaseToken: null});
|
||||||
localStorage.updateObject('settings', {desktopAlerts: false});
|
LocalStorageUtil.updateObject('settings', {desktopAlerts: false});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,10 +755,10 @@ export default class TinodeWeb extends React.Component {
|
|||||||
this.fbPush.getToken().then((refreshedToken) => {
|
this.fbPush.getToken().then((refreshedToken) => {
|
||||||
if (refreshedToken != this.state.firebaseToken) {
|
if (refreshedToken != this.state.firebaseToken) {
|
||||||
this.tinode.setDeviceToken(refreshedToken, sendToServer);
|
this.tinode.setDeviceToken(refreshedToken, sendToServer);
|
||||||
localStorage.setObject('firebase-token', refreshedToken);
|
LocalStorageUtil.setObject('firebase-token', refreshedToken);
|
||||||
}
|
}
|
||||||
this.setState({firebaseToken: refreshedToken, desktopAlerts: true});
|
this.setState({firebaseToken: refreshedToken, desktopAlerts: true});
|
||||||
localStorage.updateObject('settings', {desktopAlerts: true});
|
LocalStorageUtil.updateObject('settings', {desktopAlerts: true});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
this.handleError(err.message, 'err');
|
this.handleError(err.message, 'err');
|
||||||
console.log("Failed to retrieve firebase token", err);
|
console.log("Failed to retrieve firebase token", err);
|
||||||
@@ -759,27 +767,27 @@ export default class TinodeWeb extends React.Component {
|
|||||||
|
|
||||||
handleToggleMessageSounds(enabled) {
|
handleToggleMessageSounds(enabled) {
|
||||||
this.setState({messageSounds: enabled});
|
this.setState({messageSounds: enabled});
|
||||||
localStorage.updateObject('settings', {
|
LocalStorageUtil.updateObject('settings', {
|
||||||
messageSoundsOff: !enabled
|
messageSoundsOff: !enabled
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// User clicked Cancel button in Setting or Sign Up panel.
|
// User clicked Cancel button in Setting or Sign Up panel.
|
||||||
handleSidepanelCancel() {
|
handleSidepanelCancel() {
|
||||||
var parsed = parseUrlHash(window.location.hash);
|
var parsed = HashNavigation.parseUrlHash(window.location.hash);
|
||||||
parsed.path[0] = this.state.myUserId ? 'contacts' : '';
|
parsed.path[0] = this.state.myUserId ? 'contacts' : '';
|
||||||
if (parsed.params) {
|
if (parsed.params) {
|
||||||
delete parsed.params.code;
|
delete parsed.params.code;
|
||||||
delete parsed.params.method;
|
delete parsed.params.method;
|
||||||
delete parsed.params.tab;
|
delete parsed.params.tab;
|
||||||
}
|
}
|
||||||
navigateTo(composeUrlHash(parsed.path, parsed.params));
|
HashNavigation.navigateTo(HashNavigation.composeUrlHash(parsed.path, parsed.params));
|
||||||
this.setState({errorText: '', errorLevel: null});
|
this.setState({errorText: '', errorLevel: null});
|
||||||
}
|
}
|
||||||
|
|
||||||
// User clicked a (+) menu item.
|
// User clicked a (+) menu item.
|
||||||
handleNewTopic() {
|
handleNewTopic() {
|
||||||
navigateTo(setUrlSidePanel(window.location.hash, 'newtpk'));
|
HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, 'newtpk'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request to start a new topic. New P2P topic requires peer's name.
|
// Request to start a new topic. New P2P topic requires peer's name.
|
||||||
@@ -801,7 +809,9 @@ export default class TinodeWeb extends React.Component {
|
|||||||
// If the current URl contains the old topic name, replace it with new.
|
// If the current URl contains the old topic name, replace it with new.
|
||||||
// Update the name of the selected topic first so the navigator doen't clear
|
// Update the name of the selected topic first so the navigator doen't clear
|
||||||
// the state.
|
// the state.
|
||||||
this.setState({topicSelected: newName}, () => { navigateTo(setUrlTopic('', newName)); });
|
this.setState({topicSelected: newName}, () => {
|
||||||
|
HashNavigation.navigateTo(HashNavigation.setUrlTopic('', newName));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -853,7 +863,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
|
|
||||||
handleLogout() {
|
handleLogout() {
|
||||||
updateFavicon(0);
|
updateFavicon(0);
|
||||||
localStorage.removeItem('auth-token');
|
LocalStorageUtil.removeItem('auth-token');
|
||||||
if (this.tinode) {
|
if (this.tinode) {
|
||||||
this.tinode.onDisconnect = undefined;
|
this.tinode.onDisconnect = undefined;
|
||||||
this.tinode.disconnect();
|
this.tinode.disconnect();
|
||||||
@@ -862,7 +872,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
this.tinode = TinodeWeb.tnSetup(this.state.serverAddress, this.state.transport);
|
this.tinode = TinodeWeb.tnSetup(this.state.serverAddress, this.state.transport);
|
||||||
this.tinode.onConnect = this.handleConnected;
|
this.tinode.onConnect = this.handleConnected;
|
||||||
this.tinode.onDisconnect = this.handleDisconnect;
|
this.tinode.onDisconnect = this.handleDisconnect;
|
||||||
navigateTo('');
|
HashNavigation.navigateTo('');
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLeaveUnsubRequest(topicName) {
|
handleLeaveUnsubRequest(topicName) {
|
||||||
@@ -873,7 +883,7 @@ export default class TinodeWeb extends React.Component {
|
|||||||
|
|
||||||
topic.leave(true).then((ctrl) => {
|
topic.leave(true).then((ctrl) => {
|
||||||
// Hide MessagesView and InfoView panels.
|
// Hide MessagesView and InfoView panels.
|
||||||
navigateTo(setUrlTopic(window.location.hash, ''));
|
HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, ''));
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
this.handleError(err.message, 'err');
|
this.handleError(err.message, 'err');
|
||||||
});
|
});
|
||||||
@@ -926,12 +936,12 @@ export default class TinodeWeb extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleShowInfoView() {
|
handleShowInfoView() {
|
||||||
navigateTo(addUrlParam(window.location.hash, 'info', true));
|
HashNavigation.navigateTo(HashNavigation.addUrlParam(window.location.hash, 'info', true));
|
||||||
this.setState({showInfoPanel: true});
|
this.setState({showInfoPanel: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHideInfoView() {
|
handleHideInfoView() {
|
||||||
navigateTo(removeUrlParam(window.location.hash, 'info'));
|
HashNavigation.navigateTo(HashNavigation.removeUrlParam(window.location.hash, 'info'));
|
||||||
this.setState({showInfoPanel: false});
|
this.setState({showInfoPanel: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+89
-18
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user