forked from cory/tildefriends
		
	Split up the ssb web client into one file per vue component.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3643 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		| @@ -1 +1 @@ | ||||
| {"type":"tildefriends-app","files":{"app.js":"&qvp1qQcymJp9pWxnZXA9/VXFt6FRGj9JCAxNCt/afsU=.sha256","index.html":"&sz/uo2rG4pfYL+0sDuXhQbtnIoh8k9yxKR9i1igOtzE=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256"}} | ||||
| {"type":"tildefriends-app","files":{"app.js":"&qvp1qQcymJp9pWxnZXA9/VXFt6FRGj9JCAxNCt/afsU=.sha256","index.html":"&vMOt54ko7CqKGDOaFkozfGwOoCU4QbL2+JE9r4/zDAk=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256","tf-user.js":"&V9Ol799hM6i1PZDbAS91CMhgx7aENDTJnT+KrwK4Lh4=.sha256","tf-message.js":"&e811GqoyT6JhNrgXA1rCB/Y7ggtbOz2xcZP5+rQrrws=.sha256"}} | ||||
| @@ -7,6 +7,8 @@ | ||||
| 		<link rel="stylesheet" href="https://unpkg.com/vue-material/dist/theme/default-dark.css"> | ||||
| 		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> | ||||
| 		<script src="vue-material.js"></script> | ||||
| 		<script src="tf-user.js"></script> | ||||
| 		<script src="tf-message.js"></script> | ||||
| 		<script src="https://cdnjs.cloudflare.com/ajax/libs/commonmark/0.29.1/commonmark.min.js"></script> | ||||
| 		<script> | ||||
| 			var g_data = { | ||||
| @@ -57,148 +59,6 @@ | ||||
| 			}); | ||||
| 			window.addEventListener('load', function() { | ||||
| 				Vue.use(VueMaterial.default); | ||||
| 				Vue.component('tf-user', { | ||||
| 					data: function() { return {users: g_data.users, show_user_dialog: false, show_follow_dialog: false} }, | ||||
| 					props: ['id'], | ||||
| 					mounted: function() { | ||||
| 						window.parent.postMessage({user: this.id}, '*'); | ||||
| 					}, | ||||
| 					computed: { | ||||
| 						following: { | ||||
| 							get: function() { | ||||
| 								return g_data.users[g_data.whoami] && | ||||
| 									g_data.users[g_data.whoami].following && | ||||
| 									g_data.users[g_data.whoami].following.indexOf(this.id) != -1; | ||||
| 							}, | ||||
| 							set: function(newValue) { | ||||
| 								if (g_data.users[g_data.whoami] && | ||||
| 									g_data.users[g_data.whoami].following) { | ||||
| 									if (newValue && g_data.users[g_data.whoami].following.indexOf(this.id) == -1) { | ||||
| 										window.parent.postMessage({appendMessage: {type: "contact", following: true, contact: this.id}}, '*'); | ||||
| 									} else if (!newValue) { | ||||
| 										window.parent.postMessage({appendMessage: {type: "contact", following: false, contact: this.id}}, '*'); | ||||
| 									} | ||||
| 								} | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					template: `<span @click="show_user_dialog = true"> | ||||
| 							{{users[id] && users[id].name ? users[id].name : id}} | ||||
| 								<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 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> | ||||
| 										<md-list> | ||||
| 											<md-subheader>Followers</md-subheader> | ||||
| 											<md-list-item v-for="follower in (users[id] || []).followers" v-bind:key="'follower-' + follower"> | ||||
| 												<tf-user :id="follower"></tf-user> | ||||
| 											</md-list-item> | ||||
| 											<md-subheader>Following</md-subheader> | ||||
| 											<md-list-item v-for="user in (users[id] || []).following" v-bind:key="'following-' + user"> | ||||
| 												<tf-user :id="user"></tf-user> | ||||
| 											</md-list-item> | ||||
| 										</md-list> | ||||
| 									</md-dialog-content> | ||||
| 									<md-dialog-actions> | ||||
| 										<md-button @click="show_user_dialog = false">Close</md-button> | ||||
| 									</md-dialog-actions> | ||||
| 								</md-dialog> | ||||
| 							</span>`, | ||||
| 				}); | ||||
| 				Vue.component('tf-message', { | ||||
| 					props: ['message', 'messages'], | ||||
| 					data: function() { return { showRaw: false } }, | ||||
| 					computed: { | ||||
| 						content_json: function() { | ||||
| 							try { | ||||
| 								return JSON.parse(this.message.content); | ||||
| 							} catch { | ||||
| 								return undefined; | ||||
| 							} | ||||
| 						}, | ||||
| 						sub_messages: function() { | ||||
| 							var id = this.message.id; | ||||
| 							return this.messages.filter(function (x) { | ||||
| 								try { | ||||
| 									return JSON.parse(x.content).root == id; | ||||
| 								} catch {} | ||||
| 							}); | ||||
| 						}, | ||||
| 						votes: function() { | ||||
| 							return []; | ||||
| 							var id = this.message.id; | ||||
| 							return this.votes.filter(function (x) { | ||||
| 								try { | ||||
| 									var j = JSON.parse(x.content); | ||||
| 									return j.type == 'vote' && j.vote.link == id; | ||||
| 								} catch {} | ||||
| 							}).reduce(function (accum, value) { | ||||
| 								var expression = JSON.parse(value.content).vote.expression; | ||||
| 								if (!accum[expression]) { | ||||
| 									accum[expression] = []; | ||||
| 								} | ||||
| 								accum[expression].push(value); | ||||
| 								return accum; | ||||
| 							}, {}); | ||||
| 						} | ||||
| 					}, | ||||
| 					methods: { | ||||
| 						markdown: function(md) { | ||||
| 							var reader = new commonmark.Parser({safe: true}); | ||||
| 							var writer = new commonmark.HtmlRenderer(); | ||||
| 							return writer.render(reader.parse(md)); | ||||
| 						}, | ||||
| 						json: function(message) { | ||||
| 							try { | ||||
| 								return JSON.parse(message.content); | ||||
| 							} catch { | ||||
| 								return undefined; | ||||
| 							} | ||||
| 						}, | ||||
| 					}, | ||||
| 					template: `<md-app class="md-elevation-8" style="margin: 1em" v-if="!content_json || ['pub', 'vote'].indexOf(content_json.type) == -1"> | ||||
| <md-app-toolbar> | ||||
| 	<h3> | ||||
| 		<tf-user :id="message.author"></tf-user> | ||||
| 	</h3> | ||||
| 	<div style="font-size: x-small">{{new Date(message.timestamp)}}</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> | ||||
| 			<md-menu-content> | ||||
| 				<md-menu-item v-if="!showRaw" v-on:click="showRaw = true">View Raw</md-menu-item> | ||||
| 				<md-menu-item v-else v-on:click="showRaw = false">View Message</md-menu-item> | ||||
| 			</md-menu-content> | ||||
| 		</md-menu> | ||||
| 	</div> | ||||
| </md-app-toolbar> | ||||
| <md-app-content> | ||||
| 	<div v-if="showRaw">{{message.content}}</div> | ||||
| 	<div v-else> | ||||
| 		<div v-if="content_json && content_json.type == 'post'"> | ||||
| 			<div v-html="this.markdown(content_json.text)"></div> | ||||
| 			<img v-for="mention in content_json.mentions" v-if="mention.link && typeof(mention.link) == 'string' && mention.link.startsWith('&')" :src="'/' + mention.link + '/view'"></img> | ||||
| 		</div> | ||||
| 		<div v-else-if="content_json && content_json.type == 'tildefriends-app'"> | ||||
| 			<div v-html="this.markdown(content_json.text)"></div> | ||||
| 			<md-button target="_top" :href="'/' + message.id + '/'">{{content_json.name || 'tildefriends-app'}}</md-button> | ||||
| 		</div> | ||||
| 		<div v-else-if="content_json && content_json.type == 'contact'"><tf-user :id="message.author"></tf-user> {{content_json.following ? '==>' : '=/=>'}} <tf-user :id="content_json.contact"></tf-user></div> | ||||
| 		<div v-else>{{message.content}}</div> | ||||
| 	</div> | ||||
| 	<tf-message v-for="sub_message in sub_messages" v-bind:message="sub_message" v-bind:messages="messages" v-bind:key="sub_message.id"></tf-message> | ||||
| 	<md-chip v-for="vote in Object.keys(votes)" v-bind:key="vote"> | ||||
| 		{{vote + (votes[vote].length > 1 ? ' (' + votes[vote].length + ')' : '')}} | ||||
| 	</md-chip> | ||||
| </md-app-content> | ||||
| </md-app>`, | ||||
| 				}); | ||||
| 				function markdown(d) { return d; } | ||||
| 				Vue.config.performance = true; | ||||
| 				var vue = new Vue({ | ||||
| 					el: '#app', | ||||
| 					data: g_data, | ||||
|   | ||||
							
								
								
									
										88
									
								
								apps/cory/index/tf-message.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								apps/cory/index/tf-message.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| Vue.component('tf-message', { | ||||
| 	props: ['message', 'messages'], | ||||
| 	data: function() { return { showRaw: false } }, | ||||
| 	computed: { | ||||
| 		content_json: function() { | ||||
| 			try { | ||||
| 				return JSON.parse(this.message.content); | ||||
| 			} catch { | ||||
| 				return undefined; | ||||
| 			} | ||||
| 		}, | ||||
| 		sub_messages: function() { | ||||
| 			var id = this.message.id; | ||||
| 			return this.messages.filter(function (x) { | ||||
| 				try { | ||||
| 					return JSON.parse(x.content).root == id; | ||||
| 				} catch {} | ||||
| 			}); | ||||
| 		}, | ||||
| 		votes: function() { | ||||
| 			return []; | ||||
| 			var id = this.message.id; | ||||
| 			return this.votes.filter(function (x) { | ||||
| 				try { | ||||
| 					var j = JSON.parse(x.content); | ||||
| 					return j.type == 'vote' && j.vote.link == id; | ||||
| 				} catch {} | ||||
| 			}).reduce(function (accum, value) { | ||||
| 				var expression = JSON.parse(value.content).vote.expression; | ||||
| 				if (!accum[expression]) { | ||||
| 					accum[expression] = []; | ||||
| 				} | ||||
| 				accum[expression].push(value); | ||||
| 				return accum; | ||||
| 			}, {}); | ||||
| 		} | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		markdown: function(md) { | ||||
| 			var reader = new commonmark.Parser({safe: true}); | ||||
| 			var writer = new commonmark.HtmlRenderer(); | ||||
| 			return writer.render(reader.parse(md)); | ||||
| 		}, | ||||
| 		json: function(message) { | ||||
| 			try { | ||||
| 				return JSON.parse(message.content); | ||||
| 			} catch { | ||||
| 				return undefined; | ||||
| 			} | ||||
| 		}, | ||||
| 	}, | ||||
| 	template: `<md-app class="md-elevation-8" style="margin: 1em" v-if="!content_json || ['pub', 'vote'].indexOf(content_json.type) == -1"> | ||||
| <md-app-toolbar> | ||||
| 	<h3> | ||||
| 		<tf-user :id="message.author"></tf-user> | ||||
| 	</h3> | ||||
| 	<div style="font-size: x-small">{{new Date(message.timestamp)}}</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> | ||||
| 			<md-menu-content> | ||||
| 				<md-menu-item v-if="!showRaw" v-on:click="showRaw = true">View Raw</md-menu-item> | ||||
| 				<md-menu-item v-else v-on:click="showRaw = false">View Message</md-menu-item> | ||||
| 			</md-menu-content> | ||||
| 		</md-menu> | ||||
| 	</div> | ||||
| </md-app-toolbar> | ||||
| <md-app-content> | ||||
| 	<div v-if="showRaw">{{message.content}}</div> | ||||
| 	<div v-else> | ||||
| 		<div v-if="content_json && content_json.type == 'post'"> | ||||
| 			<div v-html="this.markdown(content_json.text)"></div> | ||||
| 			<img v-for="mention in content_json.mentions" v-if="mention.link && typeof(mention.link) == 'string' && mention.link.startsWith('&')" :src="'/' + mention.link + '/view'"></img> | ||||
| 		</div> | ||||
| 		<div v-else-if="content_json && content_json.type == 'tildefriends-app'"> | ||||
| 			<div v-html="this.markdown(content_json.text)"></div> | ||||
| 			<md-button target="_top" :href="'/' + message.id + '/'">{{content_json.name || 'tildefriends-app'}}</md-button> | ||||
| 		</div> | ||||
| 		<div v-else-if="content_json && content_json.type == 'contact'"><tf-user :id="message.author"></tf-user> {{content_json.following ? '==>' : '=/=>'}} <tf-user :id="content_json.contact"></tf-user></div> | ||||
| 		<div v-else>{{message.content}}</div> | ||||
| 	</div> | ||||
| 	<tf-message v-for="sub_message in sub_messages" v-bind:message="sub_message" v-bind:messages="messages" v-bind:key="sub_message.id"></tf-message> | ||||
| 	<md-chip v-for="vote in Object.keys(votes)" v-bind:key="vote"> | ||||
| 		{{vote + (votes[vote].length > 1 ? ' (' + votes[vote].length + ')' : '')}} | ||||
| 	</md-chip> | ||||
| </md-app-content> | ||||
| </md-app>`, | ||||
| }); | ||||
							
								
								
									
										52
									
								
								apps/cory/index/tf-user.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								apps/cory/index/tf-user.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| Vue.component('tf-user', { | ||||
| 	data: function() { return {users: g_data.users, show_user_dialog: false, show_follow_dialog: false} }, | ||||
| 	props: ['id'], | ||||
| 	mounted: function() { | ||||
| 		window.parent.postMessage({user: this.id}, '*'); | ||||
| 	}, | ||||
| 	computed: { | ||||
| 		following: { | ||||
| 			get: function() { | ||||
| 				return g_data.users[g_data.whoami] && | ||||
| 					g_data.users[g_data.whoami].following && | ||||
| 					g_data.users[g_data.whoami].following.indexOf(this.id) != -1; | ||||
| 			}, | ||||
| 			set: function(newValue) { | ||||
| 				if (g_data.users[g_data.whoami] && | ||||
| 					g_data.users[g_data.whoami].following) { | ||||
| 					if (newValue && g_data.users[g_data.whoami].following.indexOf(this.id) == -1) { | ||||
| 						window.parent.postMessage({appendMessage: {type: "contact", following: true, contact: this.id}}, '*'); | ||||
| 					} else if (!newValue) { | ||||
| 						window.parent.postMessage({appendMessage: {type: "contact", following: false, contact: this.id}}, '*'); | ||||
| 					} | ||||
| 				} | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, | ||||
| 	template: `<span @click="show_user_dialog = true"> | ||||
| 			{{users[id] && users[id].name ? users[id].name : id}} | ||||
| 				<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 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> | ||||
| 						<md-list> | ||||
| 							<md-subheader>Followers</md-subheader> | ||||
| 							<md-list-item v-for="follower in (users[id] || []).followers" v-bind:key="'follower-' + follower"> | ||||
| 								<tf-user :id="follower"></tf-user> | ||||
| 							</md-list-item> | ||||
| 							<md-subheader>Following</md-subheader> | ||||
| 							<md-list-item v-for="user in (users[id] || []).following" v-bind:key="'following-' + user"> | ||||
| 								<tf-user :id="user"></tf-user> | ||||
| 							</md-list-item> | ||||
| 						</md-list> | ||||
| 					</md-dialog-content> | ||||
| 					<md-dialog-actions> | ||||
| 						<md-button @click="show_user_dialog = false">Close</md-button> | ||||
| 					</md-dialog-actions> | ||||
| 				</md-dialog> | ||||
| 			</span>`, | ||||
| }); | ||||
		Reference in New Issue
	
	Block a user