Redid lots of things about viewing an invidual user's feed, their profile, and following users.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3740 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		@@ -1 +1 @@
 | 
			
		||||
{"type":"tildefriends-app","files":{"app.js":"&KdIfXHcm7xE6iBlJWoW8DixHbIPs+YPevJL+rF8eW4s=.sha256","index.html":"&ayK1muTik0h4UYNvT0QNm0WrygVrL8kxBoEyrQkHyHs=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256","tf-user.js":"&fXhPpneuYuseoaYk25ODN3QecFAeOfuMOZd98OgvjsQ=.sha256","tf-message.js":"&oQggZN26PtRi4Ce9HY8TKVJ9jRrYWLRE5tN+3yHwEJE=.sha256","tf.js":"&EgrrFfINhqFL/Kj8qkJwH/DHTLrZ8CxhHDBxZjcyjUY=.sha256","commonmark.min.js":"&5x6ek3tFrKTZX6hXNNyFsjmhvrjmWpUkwuuaiyVV1Us=.sha256","vue.js":"&g1wvA+yHl1sVC+eufTsg9If7ZeVyMTBU+h0tks7ZNzE=.sha256","vue-material-theme-default-dark.css":"&RP2nr+2CR18BpHHw5ST9a5GJUCOG9n0G2kuGkcQioWE=.sha256","vue-material.min.css":"&kGbUM2QgFSyHZRzqQb0b+0S3EVIlZ0AXpdiAVjIhou8=.sha256","roboto.css":"&jJv43Om673mQO5JK0jj7714s5E+5Yrf82H6LcDx7wUs=.sha256","material-icons.css":"&a28PdcVvgq/DxyIvJAx/e+ZOEtOuHnr3kjLWKyzH11M=.sha256"}}
 | 
			
		||||
{"type":"tildefriends-app","files":{"app.js":"&SJrK87ZgHkxZQDB1nm/Xej/bzajzWpiY9a384zqZVzE=.sha256","index.html":"&O8+Vr4YHP8NIORZzM3Ee9tyLXr2xCETT2Eva0rO5ebA=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256","tf-user.js":"&DdJwZYEo7AqFyutYMvEjykoVXxdHVog0UXye6Sbo0TU=.sha256","tf-message.js":"&ox9wj2+P3BhqokfHPI3ZMpSYNpNhl91K5R6Z4GbWxCA=.sha256","tf.js":"&rUCI1QKOoyWcFegV72DfG/P7HykmkX4DcvWV87hCeBM=.sha256","commonmark.min.js":"&5x6ek3tFrKTZX6hXNNyFsjmhvrjmWpUkwuuaiyVV1Us=.sha256","vue.js":"&g1wvA+yHl1sVC+eufTsg9If7ZeVyMTBU+h0tks7ZNzE=.sha256","vue-material-theme-default-dark.css":"&RP2nr+2CR18BpHHw5ST9a5GJUCOG9n0G2kuGkcQioWE=.sha256","vue-material.min.css":"&kGbUM2QgFSyHZRzqQb0b+0S3EVIlZ0AXpdiAVjIhou8=.sha256","roboto.css":"&jJv43Om673mQO5JK0jj7714s5E+5Yrf82H6LcDx7wUs=.sha256","material-icons.css":"&a28PdcVvgq/DxyIvJAx/e+ZOEtOuHnr3kjLWKyzH11M=.sha256"}}
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
const k_posts_max = 20;
 | 
			
		||||
const k_votes_max = 20;
 | 
			
		||||
 | 
			
		||||
var g_ready = false;
 | 
			
		||||
var g_selected = null;
 | 
			
		||||
 | 
			
		||||
var g_following_cache = {};
 | 
			
		||||
@@ -240,6 +241,7 @@ async function getPosts(db, ids) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function ready() {
 | 
			
		||||
	g_ready = true;
 | 
			
		||||
	return refresh(g_selected);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -267,6 +269,7 @@ async function refresh(selected) {
 | 
			
		||||
	}
 | 
			
		||||
	await Promise.all([
 | 
			
		||||
		app.postMessage({whoami: whoami}),
 | 
			
		||||
		app.postMessage({hash: selected && selected.length == 1 ? selected[0] : null}),
 | 
			
		||||
		ssb.getBroadcasts().then(broadcasts => app.postMessage({broadcasts: broadcasts})),
 | 
			
		||||
		ssb.connections().then(connections => app.postMessage({connections: connections})),
 | 
			
		||||
		core.apps().then(apps => app.postMessage({apps: apps})),
 | 
			
		||||
@@ -293,6 +296,7 @@ async function refresh(selected) {
 | 
			
		||||
			];
 | 
			
		||||
		}))),
 | 
			
		||||
	]);
 | 
			
		||||
	await app.postMessage({ready: true});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ssb.addEventListener('message', async function(id) {
 | 
			
		||||
@@ -308,7 +312,6 @@ ssb.addEventListener('message', async function(id) {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
core.register('message', async function(m) {
 | 
			
		||||
	print(JSON.stringify(m));
 | 
			
		||||
	if (m.message == 'ready') {
 | 
			
		||||
		await ready();
 | 
			
		||||
	} else if (m.message) {
 | 
			
		||||
@@ -321,9 +324,12 @@ core.register('message', async function(m) {
 | 
			
		||||
		}
 | 
			
		||||
	} else if (m.event == 'hashChange') {
 | 
			
		||||
		if (m.hash.length > 1) {
 | 
			
		||||
			refresh([m.hash.substring(1)]);
 | 
			
		||||
			g_selected = [m.hash.substring(1)];
 | 
			
		||||
		} else {
 | 
			
		||||
			refresh();
 | 
			
		||||
			g_selected = null;
 | 
			
		||||
		}
 | 
			
		||||
		if (g_ready) {
 | 
			
		||||
			await refresh(g_selected);
 | 
			
		||||
		}
 | 
			
		||||
	} else if (m.event == 'focus' || m.event == 'blur') {
 | 
			
		||||
		/* Shh. */
 | 
			
		||||
 
 | 
			
		||||
@@ -7,10 +7,10 @@
 | 
			
		||||
		<link rel="stylesheet" href="vue-material-theme-default-dark.css">
 | 
			
		||||
		<script src="vue.js"></script>
 | 
			
		||||
		<script src="vue-material.js"></script>
 | 
			
		||||
		<script src="commonmark.min.js"></script>
 | 
			
		||||
		<script src="tf-user.js"></script>
 | 
			
		||||
		<script src="tf-message.js"></script>
 | 
			
		||||
		<script src="tf.js"></script>
 | 
			
		||||
		<script src="commonmark.min.js"></script>
 | 
			
		||||
	</head>
 | 
			
		||||
	<body style="color: #fff">
 | 
			
		||||
		<div id="app">
 | 
			
		||||
@@ -38,8 +38,6 @@
 | 
			
		||||
						<md-subheader>Connections</md-subheader>
 | 
			
		||||
						<md-list-item v-for="connection in connections" v-bind:key="'connection-' + JSON.stringify(connection)"><tf-user :id="connection"></tf-user></md-list-item>
 | 
			
		||||
						<md-list-item @click="show_connect_dialog = true">Connect</md-list-item>
 | 
			
		||||
						<md-subheader>Users</md-subheader>
 | 
			
		||||
						<!-- <md-list-item v-for="user in Object.keys(users).sort((x, y) => (users[x].name || x).localeCompare(users[y].name || y))" v-bind:key="'user-' + user"><tf-user v-bind:id="user"/></md-list-item> -->
 | 
			
		||||
					</md-list>
 | 
			
		||||
				</md-app-drawer>
 | 
			
		||||
				<md-app-toolbar class="md-secondary" v-show="unread > 0">
 | 
			
		||||
@@ -74,6 +72,58 @@
 | 
			
		||||
							<md-button class="md-raised md-primary" v-on:click="post_message()">Submit Post</md-button>
 | 
			
		||||
						</md-card-actions>
 | 
			
		||||
					</md-card>
 | 
			
		||||
 | 
			
		||||
					<md-button v-if="selected" class="md-raised md-primary" style="margin: 1em" @click="set_hash(null)">
 | 
			
		||||
						<md-icon>home</md-icon> Home
 | 
			
		||||
					</md-button>
 | 
			
		||||
 | 
			
		||||
					<md-card v-if="selected && selected.charAt(0) == '@'" class="md-raised md-elevation-8" style="margin: 1em">
 | 
			
		||||
						<md-card-header>
 | 
			
		||||
							<md-card-header-text>
 | 
			
		||||
								<div class="md-title">{{users[selected] && users[selected].name ? users[selected].name : selected}}</div>
 | 
			
		||||
								<div class="md-subhead" v-if="users[selected] && users[selected].name">{{selected}}</div>
 | 
			
		||||
							</md-card-header-text>
 | 
			
		||||
							<md-card-media v-if="users[selected] && users[selected].image" class="md-medium">
 | 
			
		||||
								<div><img :src="'/' + (typeof(users[selected].image) == 'string' ? users[selected].image : users[selected].image.link) + '/view'"></div>
 | 
			
		||||
							</md-card-media>
 | 
			
		||||
						</md-card-header>
 | 
			
		||||
						<md-card-content>
 | 
			
		||||
							<div v-if="selected == whoami">
 | 
			
		||||
								<md-field>
 | 
			
		||||
									<label>Name</label>
 | 
			
		||||
									<md-input v-model="edit_profile_name"></md-input>
 | 
			
		||||
								</md-field>
 | 
			
		||||
								<md-field>
 | 
			
		||||
									<label>Description</label>
 | 
			
		||||
									<md-textarea v-model="edit_profile_description"></md-textarea>
 | 
			
		||||
								</md-field>
 | 
			
		||||
							</div>
 | 
			
		||||
							<template v-if="users[selected]">
 | 
			
		||||
								<div v-if="users[selected].name">{{selected}}</div>
 | 
			
		||||
								<div v-html="markdown(users[selected].description)"></div>
 | 
			
		||||
							</template>
 | 
			
		||||
							<md-card-actions>
 | 
			
		||||
								<md-menu md-size="small" v-if="users[selected] && users[selected].followers">
 | 
			
		||||
									<md-button md-menu-trigger>{{Object.keys(users[selected].followers).length}} followers</md-button>
 | 
			
		||||
									<md-menu-content>
 | 
			
		||||
										<md-menu-item v-for="id of Object.keys(users[selected].followers)"><tf-user :id="id"></tf-user></md-menu-item>
 | 
			
		||||
									</md-menu-content>
 | 
			
		||||
								</md-menu>
 | 
			
		||||
								<md-menu md-size="small" v-if="users[selected] && users[selected].following">
 | 
			
		||||
									<md-button md-menu-trigger>{{Object.keys(users[selected].following).length}} following</md-button>
 | 
			
		||||
									<md-menu-content>
 | 
			
		||||
										<md-menu-item v-for="id of Object.keys(users[selected].following)"><tf-user :id="id"></tf-user></md-menu-item>
 | 
			
		||||
									</md-menu-content>
 | 
			
		||||
								</md-menu>
 | 
			
		||||
								<template v-if="selected != whoami && users[whoami]">
 | 
			
		||||
									<md-button @click="follow(selected)" v-if="!users[whoami].following[selected]" class="md-raised md-secondary">Follow</md-button>
 | 
			
		||||
									<md-button @click="unfollow(selected)" v-else class="md-raised md-secondary">Unfollow</md-button>
 | 
			
		||||
								</template>
 | 
			
		||||
								<md-button @click="save_profile" v-if="selected == whoami" class="md-primary md-raised">Save Profile</md-button>
 | 
			
		||||
							</md-card-actions>
 | 
			
		||||
						</md-card-content>
 | 
			
		||||
					</md-card>
 | 
			
		||||
 | 
			
		||||
					<template v-if="messages.length">
 | 
			
		||||
						<tf-message
 | 
			
		||||
							v-for="message in messages"
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,10 @@ Vue.component('tf-message', {
 | 
			
		||||
	<h3>
 | 
			
		||||
		<tf-user :id="message.author"></tf-user>
 | 
			
		||||
	</h3>
 | 
			
		||||
	<div style="font-size: x-small">{{new Date(message.timestamp)}}</div>
 | 
			
		||||
	<div style="font-size: x-small">
 | 
			
		||||
		{{new Date(message.timestamp)}}
 | 
			
		||||
		<md-tooltip>{{message.id}}</md-tooltip>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div class="md-toolbar-section-end">
 | 
			
		||||
		<md-menu>
 | 
			
		||||
			<md-button md-menu-trigger class="md-icon-button"><md-icon>more_vert</md-icon></md-button>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,5 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
Vue.component('tf-user', {
 | 
			
		||||
	data: function() { return {
 | 
			
		||||
		show_user_dialog: false,
 | 
			
		||||
		show_follow_dialog: false,
 | 
			
		||||
		edit_profile_name: null,
 | 
			
		||||
		edit_profile_description: null,
 | 
			
		||||
	} },
 | 
			
		||||
	props: ['id'],
 | 
			
		||||
	computed: {
 | 
			
		||||
		following: {
 | 
			
		||||
@@ -15,91 +9,17 @@ Vue.component('tf-user', {
 | 
			
		||||
					g_data.users[g_data.whoami].following &&
 | 
			
		||||
					g_data.users[g_data.whoami].following[this.id];
 | 
			
		||||
			},
 | 
			
		||||
			set: function(newValue) {
 | 
			
		||||
				var already_following =
 | 
			
		||||
					g_data.users &&
 | 
			
		||||
					g_data.users[g_data.whoami] &&
 | 
			
		||||
					g_data.users[g_data.whoami].following &&
 | 
			
		||||
					g_data.users[g_data.whoami].following[this.id];
 | 
			
		||||
				if (newValue && !already_following) {
 | 
			
		||||
					if (confirm("Are you sure you want to follow " + this.id + "?")) {
 | 
			
		||||
						window.parent.postMessage({appendMessage: {type: "contact", following: true, contact: this.id}}, '*');
 | 
			
		||||
					}
 | 
			
		||||
				} else if (!newValue && already_following) {
 | 
			
		||||
					if (confirm("Are you sure you want to unfollow " + this.id + "?")) {
 | 
			
		||||
						window.parent.postMessage({appendMessage: {type: "contact", following: false, contact: this.id}}, '*');
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		whoami: { get: function() { return g_data.whoami; } },
 | 
			
		||||
		users: { get: function() { return g_data.users; } },
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
		save_profile: function() {
 | 
			
		||||
			var message = {appendMessage: {
 | 
			
		||||
				type: 'about',
 | 
			
		||||
				about: this.id,
 | 
			
		||||
				name: this.edit_profile_name,
 | 
			
		||||
				description: this.edit_profile_description,
 | 
			
		||||
			}};
 | 
			
		||||
			window.parent.postMessage(message, '*');
 | 
			
		||||
		},
 | 
			
		||||
		show_user: function() {
 | 
			
		||||
			window.parent.postMessage({action: 'setHash', hash: this.id}, '*');
 | 
			
		||||
			if (this.id == this.whoami) {
 | 
			
		||||
				this.edit_profile_name = this.users[this.id].name;
 | 
			
		||||
				this.edit_profile_description = this.users[this.id].description;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	template: `<span>
 | 
			
		||||
				<md-chip md-clickable :class="following ? 'md-accent' : ''" @click="show_user()">
 | 
			
		||||
	template: `<md-chip md-clickable :class="following ? 'md-accent' : ''" @click="show_user()">
 | 
			
		||||
					{{users[id] && users[id].name ? users[id].name : id}}
 | 
			
		||||
				</md-chip>
 | 
			
		||||
				<md-tooltip v-if="users[id] && users[id].name">{{id}}</md-tooltip>
 | 
			
		||||
				<md-dialog :md-active.sync="show_user_dialog">
 | 
			
		||||
					<md-dialog-title>{{users[id] && users[id].name ? users[id].name : id}}</md-dialog-title>
 | 
			
		||||
					<md-dialog-content>
 | 
			
		||||
						<div v-if="id == whoami">
 | 
			
		||||
							<md-field>
 | 
			
		||||
								<label>Name</label>
 | 
			
		||||
								<md-input v-model="edit_profile_name"></md-input>
 | 
			
		||||
							</md-field>
 | 
			
		||||
							<md-field>
 | 
			
		||||
								<label>Description</label>
 | 
			
		||||
								<md-textarea v-model="edit_profile_description"></md-textarea>
 | 
			
		||||
							</md-field>
 | 
			
		||||
						</div>
 | 
			
		||||
						<template v-if="users[id]">
 | 
			
		||||
							<div v-if="users[id].image"><img :src="'/' + users[id].image + '/view'"></div>
 | 
			
		||||
							<div v-if="users[id].name">{{id}}</div>
 | 
			
		||||
							<div>{{users[id].description}}</div>
 | 
			
		||||
							<div><md-switch v-model="following">Following</md-switch></div>
 | 
			
		||||
							<div class="md-layout">
 | 
			
		||||
								<div class="md-layout-item">
 | 
			
		||||
									<md-list>
 | 
			
		||||
										<md-subheader>Followers</md-subheader>
 | 
			
		||||
										<md-list-item v-for="follower in Object.keys((users[id] && users[id].followers) ? users[id].followers : {})" v-bind:key="'follower-' + follower">
 | 
			
		||||
											<tf-user :id="follower"></tf-user>
 | 
			
		||||
										</md-list-item>
 | 
			
		||||
									</md-list>
 | 
			
		||||
								</div>
 | 
			
		||||
								<div class="md-layout-item">
 | 
			
		||||
									<md-list>
 | 
			
		||||
										<md-subheader>Following</md-subheader>
 | 
			
		||||
										<md-list-item v-for="user in Object.keys((users[id] && users[id].following) ? users[id].following : {})" v-bind:key="'following-' + user">
 | 
			
		||||
											<tf-user :id="user"></tf-user>
 | 
			
		||||
										</md-list-item>
 | 
			
		||||
									</md-list>
 | 
			
		||||
								</div>
 | 
			
		||||
							</div>
 | 
			
		||||
						</template>
 | 
			
		||||
					</md-dialog-content>
 | 
			
		||||
					<md-dialog-actions>
 | 
			
		||||
						<md-button @click="save_profile" v-if="id == whoami">Save Profile</md-button>
 | 
			
		||||
						<md-button @click="show_user_dialog = false">Close</md-button>
 | 
			
		||||
					</md-dialog-actions>
 | 
			
		||||
				</md-dialog>
 | 
			
		||||
			</span>`,
 | 
			
		||||
					<md-tooltip v-if="users[id] && users[id].name">{{id}}</md-tooltip>
 | 
			
		||||
				</md-chip>`,
 | 
			
		||||
});
 | 
			
		||||
@@ -16,12 +16,20 @@ var g_data = {
 | 
			
		||||
	mentions: {},
 | 
			
		||||
	unread: 0,
 | 
			
		||||
	loading: true,
 | 
			
		||||
	selected: null,
 | 
			
		||||
	edit_profile_name: null,
 | 
			
		||||
	edit_profile_description: null,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var g_data_initial = JSON.parse(JSON.stringify(g_data));
 | 
			
		||||
var g_message_queue = [];
 | 
			
		||||
var g_process_pending = false;
 | 
			
		||||
 | 
			
		||||
function updateEditUser() {
 | 
			
		||||
	g_data.edit_profile_name = g_data.users[g_data.whoami] ? g_data.users[g_data.whoami].name : null;
 | 
			
		||||
	g_data.edit_profile_description = g_data.users[g_data.whoami] ? g_data.users[g_data.whoami].description : null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function processMessages() {
 | 
			
		||||
	for (let event of g_message_queue) {
 | 
			
		||||
		var key = Object.keys(event.data)[0];
 | 
			
		||||
@@ -56,6 +64,9 @@ function processMessages() {
 | 
			
		||||
			g_data[key + 's'].push(event.data[key]);
 | 
			
		||||
		} else if (key == 'user') {
 | 
			
		||||
			Vue.set(g_data.users, event.data.user.user, Object.assign({}, g_data.users[event.data.user.user] || {}, event.data.user.about));
 | 
			
		||||
			if (event.data.user.user == g_data.whoami) {
 | 
			
		||||
				updateEditUser();
 | 
			
		||||
			}
 | 
			
		||||
		} else if (key == 'followers') {
 | 
			
		||||
			if (!g_data.users[event.data.followers.id]) {
 | 
			
		||||
				Vue.set(g_data.users, event.data.followers.id, {});
 | 
			
		||||
@@ -104,7 +115,10 @@ function processMessages() {
 | 
			
		||||
		} else if (key == 'unread') {
 | 
			
		||||
			g_data.unread += event.data.unread;
 | 
			
		||||
		} else if (key == 'hash') {
 | 
			
		||||
			console.log(event.data);
 | 
			
		||||
			g_data.selected = event.data.hash;
 | 
			
		||||
			if (g_data.selected == g_data.whoami) {
 | 
			
		||||
				updateEditUser();
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			g_data[key] = event.data[key];
 | 
			
		||||
		}
 | 
			
		||||
@@ -155,6 +169,14 @@ window.addEventListener('load', function() {
 | 
			
		||||
					return undefined;
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			markdown: function(md) {
 | 
			
		||||
				if (!md) {
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
				var reader = new commonmark.Parser({safe: true});
 | 
			
		||||
				var writer = new commonmark.HtmlRenderer();
 | 
			
		||||
				return writer.render(reader.parse(md));
 | 
			
		||||
			},
 | 
			
		||||
			refresh: function() {
 | 
			
		||||
				window.parent.postMessage({refresh: true}, '*');
 | 
			
		||||
			},
 | 
			
		||||
@@ -168,6 +190,28 @@ window.addEventListener('load', function() {
 | 
			
		||||
			remove_from_mentions: function(link) {
 | 
			
		||||
				Vue.delete(g_data.mentions, link);
 | 
			
		||||
			},
 | 
			
		||||
			save_profile: function() {
 | 
			
		||||
				var message = {appendMessage: {
 | 
			
		||||
					type: 'about',
 | 
			
		||||
					about: g_data.selected,
 | 
			
		||||
					name: g_data.edit_profile_name,
 | 
			
		||||
					description: g_data.edit_profile_description,
 | 
			
		||||
				}};
 | 
			
		||||
				window.parent.postMessage(message, '*');
 | 
			
		||||
			},
 | 
			
		||||
			follow: function(id) {
 | 
			
		||||
				if (confirm('Are you sure you want to follow ' + id + '?')) {
 | 
			
		||||
					window.parent.postMessage({appendMessage: {type: "contact", following: true, contact: id}}, '*');
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			unfollow: function(id) {
 | 
			
		||||
				if (confirm('Are you sure you want to unfollow ' + id + '?')) {
 | 
			
		||||
					window.parent.postMessage({appendMessage: {type: "contact", following: false, contact: id}}, '*');
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			set_hash(hash) {
 | 
			
		||||
				window.parent.postMessage({action: 'setHash', hash: hash ? hash : '#'}, '*');
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
	window.parent.postMessage('ready', '*');
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user