fix safari logout, move menu to its own file, fix pm webtorrent

This commit is contained in:
Martti Malmi 2021-08-11 11:30:59 +03:00
parent f7566f7da7
commit 7aa1764ffd
5 changed files with 100 additions and 89 deletions

View File

@ -1,6 +1,5 @@
import Component from './BaseComponent'; import Component from './BaseComponent';
import { Router } from 'preact-router'; import { Router } from 'preact-router';
import { Link } from 'preact-router/match';
import {Helmet} from "react-helmet"; import {Helmet} from "react-helmet";
import Helpers from './Helpers.js'; import Helpers from './Helpers.js';
@ -8,7 +7,6 @@ import { html } from 'htm/preact';
import QRScanner from './QRScanner.js'; import QRScanner from './QRScanner.js';
import PeerManager from './PeerManager.js'; import PeerManager from './PeerManager.js';
import Session from './Session.js'; import Session from './Session.js';
import { translate as t } from './Translation.js';
import Settings from './views/Settings.js'; import Settings from './views/Settings.js';
import LogoutConfirmation from './views/LogoutConfirmation.js'; import LogoutConfirmation from './views/LogoutConfirmation.js';
@ -27,14 +25,12 @@ import Explorer from './views/Explorer.js';
import Contacts from './views/Contacts.js'; import Contacts from './views/Contacts.js';
import Torrent from './views/Torrent.js'; import Torrent from './views/Torrent.js';
import Menu from './components/Menu.js';
import VideoCall from './components/VideoCall.js'; import VideoCall from './components/VideoCall.js';
import Identicon from './components/Identicon.js';
import MediaPlayer from './components/MediaPlayer.js'; import MediaPlayer from './components/MediaPlayer.js';
import Footer from './components/Footer.js'; import Footer from './components/Footer.js';
import State from './State.js'; import State from './State.js';
import Icons from './Icons.js';
import logo from '../assets/img/icon128.png';
import logoType from '../assets/img/iris_logotype.png'; import logoType from '../assets/img/iris_logotype.png';
import '../css/style.css'; import '../css/style.css';
@ -50,63 +46,6 @@ PeerManager.init();
Helpers.checkColorScheme(); Helpers.checkColorScheme();
const APPLICATIONS = [ // TODO: move editable shortcuts to localState gun
{url: '/', text: t('home'), icon: Icons.home},
{url: '/media', text: t('media'), icon: Icons.play},
{url: '/chat', text: t('messages'), icon: Icons.chat},
{url: '/store', text: t('market'), icon: Icons.store},
{url: '/contacts', text: t('contacts'), icon: Icons.user},
{url: '/settings', text: t('settings'), icon: Icons.settings},
{url: '/explorer', text: t('explorer'), icon: Icons.folder},
{url: '/about', text: t('about')},
];
class Menu extends Component {
componentDidMount() {
State.local.get('unseenTotal').on(this.inject());
}
menuLinkClicked() {
State.local.get('toggleMenu').put(false);
State.local.get('scrollUp').put(true);
}
render() {
const pub = Session.getPubKey();
return html`
<div class="application-list">
${Helpers.isElectron ? html`<div class="electron-padding"/>` : html`
<a href="/" onClick=${() => this.menuLinkClicked()} class="hidden-xs" tabindex="0" class="logo">
<img class="hidden-xs" src=${logo} width=40 height=40/>
<img src=${logoType} height=23 width=41 />
</a>
`}
<div class="visible-xs-block">
<${Link} onClick=${() => this.menuLinkClicked()} activeClassName="active" href="/profile/${pub}">
<span class="icon"><${Identicon} str=${pub} width=40/></span>
<span class="text" style="font-size: 1.2em;border:0;margin-left: 7px;"><iris-text user="${pub}" path="profile/name" editable="false"/></span>
<//>
<br/><br/>
</div>
${APPLICATIONS.map(a => {
if (a.url) {
return html`
<${a.native ? 'a' : Link} onClick=${() => this.menuLinkClicked()} activeClassName="active" href=${a.url}>
<span class="icon">
${a.text === t('messages') && this.state.unseenTotal ? html`<span class="unseen unseen-total">${this.state.unseenTotal}</span>`: ''}
${a.icon || Icons.circle}
</span>
<span class="text">${a.text}</span>
<//>`;
}
return html`<br/><br/>`;
})}
</div>
`;
}
}
class Main extends Component { class Main extends Component {
componentDidMount() { componentDidMount() {
State.local.get('loggedIn').on(this.inject()); State.local.get('loggedIn').on(this.inject());

View File

@ -226,8 +226,25 @@ async function createChatLink() {
} }
function clearIndexedDB() { function clearIndexedDB() {
window.indexedDB.deleteDatabase('State.local'); return new Promise(resolve => {
window.indexedDB.deleteDatabase('radata'); const r1 = window.indexedDB.deleteDatabase('State.local');
const r2 = window.indexedDB.deleteDatabase('radata');
let r1done;
let r2done;
const check = () => {
r1done && r2done && resolve();
}
r1.onerror = r2.onerror = e => console.error(e);
//r1.onblocked = r2.onblocked = e => console.error('blocked', e);
r1.onsuccess = () => {
r1done = true;
check();
}
r2.onsuccess = () => {
r2done = true;
check();
}
});
} }
function getMyChatLink() { function getMyChatLink() {
@ -252,7 +269,7 @@ async function logOut() {
} }
} }
} }
await clearIndexedDB(); clearIndexedDB();
localStorage.clear(); localStorage.clear();
route('/'); route('/');
location.reload(); location.reload();
@ -277,6 +294,8 @@ function init(options = {}) {
login(JSON.parse(localStorageKey)); login(JSON.parse(localStorageKey));
} else if (options.autologin) { } else if (options.autologin) {
loginAsNewUser(name); loginAsNewUser(name);
} else {
clearIndexedDB();
} }
} }

View File

@ -2,6 +2,7 @@ import { Component } from 'preact';
import Helpers from '../Helpers.js'; import Helpers from '../Helpers.js';
import { html } from 'htm/preact'; import { html } from 'htm/preact';
import { translate as t } from '../Translation.js'; import { translate as t } from '../Translation.js';
import Torrent from './Torrent';
import State from '../State.js'; import State from '../State.js';
import Session from '../Session.js'; import Session from '../Session.js';
import iris from 'iris-lib'; import iris from 'iris-lib';
@ -30,12 +31,12 @@ class ChatMessageForm extends Component {
} }
} }
componentDidUpdate(prevProps, prevState) { componentDidUpdate() {
if (!iris.util.isMobile && this.props.autofocus !== false) { if (!iris.util.isMobile && this.props.autofocus !== false) {
$(this.base).find(".new-msg").focus(); $(this.base).find(".new-msg").focus();
} }
if (this.state.torrentId && this.state.torrentId !== prevState.torrentId) { if ($('#attachment-preview:visible').length) {
this.downloadWebtorrent(this.state.torrentId); $('#attachment-preview').append($('#webtorrent'));
} }
} }
@ -69,30 +70,13 @@ class ChatMessageForm extends Component {
this.picker.pickerVisible ? this.picker.hidePicker() : this.picker.showPicker(event.target); this.picker.pickerVisible ? this.picker.hidePicker() : this.picker.showPicker(event.target);
} }
async downloadWebtorrent(torrentId) {
function onTorrent(torrent) {
// Torrents can contain many files. Let's use the .mp4 file
let file = torrent.files.find((file) => {
return file.name.endsWith('.mp4')
})
// Stream the file in the browser
file.appendTo('#webtorrent', {autoplay: true, muted: true})
}
const client = await Helpers.getWebTorrentClient();
const existing = client.get(torrentId);
if (existing) {
onTorrent(existing);
} else {
client.add(torrentId, onTorrent);
}
}
onMsgTextPaste(event) { onMsgTextPaste(event) {
const pasted = (event.clipboardData || window.clipboardData).getData('text'); const pasted = (event.clipboardData || window.clipboardData).getData('text');
const magnetRegex = /^magnet:\?xt=urn:btih:*/; const magnetRegex = /^magnet:\?xt=urn:btih:*/;
if (pasted !== this.state.torrentId && pasted.indexOf('.torrent') > -1 || pasted.match(magnetRegex)) { if (pasted !== this.state.torrentId && pasted.indexOf('.torrent') > -1 || pasted.match(magnetRegex)) {
event.preventDefault(); event.preventDefault();
this.setState({torrentId: pasted}); this.setState({torrentId: pasted});
this.openAttachmentsPreview();
} }
} }
@ -160,6 +144,7 @@ class ChatMessageForm extends Component {
Session.channels[this.props.activeChat].attachments = null; Session.channels[this.props.activeChat].attachments = null;
} }
Helpers.scrollToMessageListBottom(); Helpers.scrollToMessageListBottom();
this.setState({torrentId:null});
} }
async webPush(msg) { async webPush(msg) {
@ -206,7 +191,9 @@ class ChatMessageForm extends Component {
<input name="attachment-input" type="file" class="hidden attachment-input" accept="image/*" multiple onChange=${() => this.openAttachmentsPreview()}/> <input name="attachment-input" type="file" class="hidden attachment-input" accept="image/*" multiple onChange=${() => this.openAttachmentsPreview()}/>
<input onPaste=${e => this.onMsgTextPaste(e)} onInput=${e => this.onMsgTextInput(e)} class="new-msg" type="text" placeholder="${t('type_a_message')}" autocomplete="off" autocorrect="off" autocapitalize="sentences" spellcheck="off"/> <input onPaste=${e => this.onMsgTextPaste(e)} onInput=${e => this.onMsgTextInput(e)} class="new-msg" type="text" placeholder="${t('type_a_message')}" autocomplete="off" autocorrect="off" autocapitalize="sentences" spellcheck="off"/>
${submitButton} ${submitButton}
<div id="webtorrent"></div> <div id="webtorrent">
${this.state.torrentId ? html`<${Torrent} preview=${true} torrentId=${this.state.torrentId}/>` : ''}
</div>
</form>`; </form>`;
} }

68
src/js/components/Menu.js Normal file
View File

@ -0,0 +1,68 @@
import Component from "../BaseComponent";
import State from "../State";
import Session from "../Session";
import {html} from "htm/preact";
import Helpers from "../Helpers";
import logo from "../../assets/img/icon128.png";
import logoType from "../../assets/img/iris_logotype.png";
import {Link} from "preact-router/match";
import Identicon from "./Identicon";
import {translate as t} from "../Translation";
import Icons from "../Icons";
const APPLICATIONS = [ // TODO: move editable shortcuts to localState gun
{url: '/', text: t('home'), icon: Icons.home},
{url: '/media', text: t('media'), icon: Icons.play},
{url: '/chat', text: t('messages'), icon: Icons.chat},
{url: '/store', text: t('market'), icon: Icons.store},
{url: '/contacts', text: t('contacts'), icon: Icons.user},
{url: '/settings', text: t('settings'), icon: Icons.settings},
{url: '/explorer', text: t('explorer'), icon: Icons.folder},
{url: '/about', text: t('about')},
];
export default class Menu extends Component {
componentDidMount() {
State.local.get('unseenTotal').on(this.inject());
}
menuLinkClicked() {
State.local.get('toggleMenu').put(false);
State.local.get('scrollUp').put(true);
}
render() {
const pub = Session.getPubKey();
return html`
<div class="application-list">
${Helpers.isElectron ? html`<div class="electron-padding"/>` : html`
<a href="/" onClick=${() => this.menuLinkClicked()} class="hidden-xs" tabindex="0" class="logo">
<img class="hidden-xs" src=${logo} width=40 height=40/>
<img src=${logoType} height=23 width=41 />
</a>
`}
<div class="visible-xs-block">
<${Link} onClick=${() => this.menuLinkClicked()} activeClassName="active" href="/profile/${pub}">
<span class="icon"><${Identicon} str=${pub} width=40/></span>
<span class="text" style="font-size: 1.2em;border:0;margin-left: 7px;"><iris-text user="${pub}" path="profile/name" editable="false"/></span>
<//>
<br/><br/>
</div>
${APPLICATIONS.map(a => {
if (a.url) {
return html`
<${a.native ? 'a' : Link} onClick=${() => this.menuLinkClicked()} activeClassName="active" href=${a.url}>
<span class="icon">
${a.text === t('messages') && this.state.unseenTotal ? html`<span class="unseen unseen-total">${this.state.unseenTotal}</span>`: ''}
${a.icon || Icons.circle}
</span>
<span class="text">${a.text}</span>
<//>`;
}
return html`<br/><br/>`;
})}
</div>
`;
}
}

View File

@ -261,9 +261,7 @@ class Chat extends View {
${this.props.id && this.props.id.length > 20 ? html` ${this.props.id && this.props.id.length > 20 ? html`
<div class="main-view" id="message-view" onScroll=${e => this.onMessageViewScroll(e)}> <div class="main-view" id="message-view" onScroll=${e => this.onMessageViewScroll(e)}>
<div id="message-list"> <div id="message-list">
<div id="topsentinel"></div>
${msgListContent} ${msgListContent}
<div id="bottomsentinel"></div>
</div> </div>
<div id="attachment-preview" class="attachment-preview" style="display:none"></div> <div id="attachment-preview" class="attachment-preview" style="display:none"></div>
</div>` : html`<${NewChat}/>` </div>` : html`<${NewChat}/>`