xssbook/public/js/profile.js
Tyler Murphy f02524b592 friends
2023-02-14 19:28:10 -05:00

369 lines
11 KiB
JavaScript

import { div, pfp, banner, parse, button, body, a, span, crawl, parseDate, parseMonth } from './main.js'
import { loadself, loadusers, loadusersposts, updateavatar, updatebanner, logout, follow, follow_status, friends } from './api.js'
import { parsePost, parseUser, header } from './components.js'
function swap(tab) {
let post_button = document.querySelector("#profilepostbutton");
let about_button = document.querySelector("#profileaboutbutton");
let friends_button = document.querySelector("#profilefriendsbutton");
let posts_section = document.querySelector("#posts");
let about_section = document.querySelector("#about");
let friends_section = document.querySelector("#friends");
let load = document.querySelector(".loadp");
if (tab === 0) {
post_button.classList.add("selected")
about_button.classList.remove("selected")
friends_button.classList.remove("selected")
posts_section.classList.remove("hidden")
about_section.classList.add("hidden")
friends_section.classList.add("hidden")
if (load) {
load.classList.remove("hidden")
}
} else if (tab === 1) {
post_button.classList.remove("selected")
about_button.classList.add("selected")
friends_button.classList.remove("selected")
posts_section.classList.add("hidden")
about_section.classList.remove("hidden")
friends_section.classList.add("hidden")
if (load) {
load.classList.add("hidden")
}
} else if (tab === 2) {
post_button.classList.remove("selected")
about_button.classList.remove("selected")
friends_button.classList.add("selected")
posts_section.classList.add("hidden")
about_section.classList.add("hidden")
friends_section.classList.remove("hidden")
if (load) {
load.classList.add("hidden")
}
}
}
function changeimage(fn) {
var input = document.createElement('input')
input.type = 'file'
input.accept= 'image/png'
input.onchange = async (e) => {
var popup = document.getElementById("popup")
var loader = popup.getElementsByClassName("loading")[0]
var message = popup.getElementsByClassName("message")[0]
loader.classList.add("hidden")
message.innerHTML = '';
popup.classList.remove("hidden")
var file = e.target.files[0];
if (file.type !== 'image/png') {
message.innerHTML = 'Image must be a PNG';
return
}
loader.classList.remove("hidden")
let response = await fn(file);
loader.classList.add("hidden")
message.innerHTML = response.msg
}
input.click();
}
function status_text(status) {
switch (status) {
case 1:
return 'Following ✓'
case 2:
return 'Follow Back'
case 3:
return 'Friends ✓'
default:
return 'Follow'
}
}
async function render() {
let status;
if (!isself) {
let response = await follow_status(data.user.user_id)
if (response.status == 200) {
status = parseInt(response.msg)
} else {
status = 0;
}
}
let friends_arr = (await friends(data.user.user_id)).json
if (friends_arr == undefined) {
friends_arr = []
}
let new_body =
body({},
...header(false, false, data.self.user_id),
div({id: 'top'},
div({id: 'banner'},
div({class: 'bg'},
banner(data.user.user_id)
),
isself ? div({class: 'changebanner', onclick: () => changeimage(updatebanner)}) : parse(''),
),
div({id: 'info'},
div({class: 'face'},
pfp(data.user.user_id),
isself ? div({class: 'changeavatar', onclick: () => changeimage(updateavatar)}) : parse(''),
),
div({class: 'infodata'},
span({class: 'bold ltext'},
parse(data.user.firstname + ' ' + data.user.lastname)
),
span({class: 'gtext'},
parse('Joined ' + parseDate(new Date(data.user.date)))
)
),
!isself ?
div({class: 'right'},
div({class: `follow ${status == 3 ? 'friend' : ''}`, onclick: async (event) => {
let button = event.target
if (button.tagName == 'SPAN') {
button = button.parentElement
}
let response
if (status % 2 == 0) {
response = await follow(true, data.user.user_id);
} else {
response = await follow(false, data.user.user_id);
}
if (response.status == 200) {
status = parseInt(response.msg)
} else {
return
}
button.firstChild.innerHTML = status_text(status)
if (status == 3) {
button.classList.add('friend')
} else {
button.classList.remove('friend')
}
}},
span({class: 'gtext'},
parse(status_text(status))
)
)
)
: parse('')
),
div({class: 'fullline', style: 'width: 80em; margin-bottom: 0; z-index: 0;'}),
div({class: 'profilebuttons'},
button({id: 'profilepostbutton', class: 'selected', onclick: () => swap(0)},
parse('Posts')
),
button({id: 'profileaboutbutton', onclick: () => swap(1)},
parse('About')
),
button({id: 'profilefriendsbutton', onclick: () => swap(2)},
parse('Friends')
),
div({style: 'flex: 20'}),
isself ? button({class: 'logout', onclick: async () => {
const response = await logout()
if (response.status != 200) return;
location.href = '/login'
}},
parse('Logout')
)
: parse('')
)
),
div({id: 'posts'},
...data.posts.map(p => parsePost(p, data.users, data.self))
),
div({id: 'load'},
a({class: 'loadp bold gtext', onclick: async () => {
const posts = await load()
data.posts.push(... posts)
const el = document.getElementById("posts")
for (const post of posts) {
el.appendChild(
parsePost(post, data.users, data.self)
)
}
}},
parse('Load more posts')
)
),
div({id: 'about', class: 'post hidden'},
span({class: 'bold ltext'},
parse('About')
),
div({class: 'data'},
span({class: 'gtext bold'},
parse('Name: ' + data.user.firstname + ' ' + data.user.lastname)
),
span({class: 'gtext bold'},
parse('Email: ' + data.user.email)
),
span({class: 'gtext bold'},
parse('Gender ' + data.user.gender)
),
span({class: 'gtext bold'},
parse('Birthday: ' + parseMonth(data.user.month) + ' ' + data.user.day + ', ' + data.user.year)
),
span({class: 'gtext bold'},
parse('User ID: ' + data.user_id)
)
)
),
div({id: 'friends', class: 'hidden'},
...friends_arr.map(u => parseUser(u))
),
div({id: 'popup', class: 'hidden'},
div({class: 'createpost'},
div({class: 'close', onclick: () => document.getElementById('popup').classList.add('hidden')}),
span({class: 'ltext ctext bold'},
parse('Uploading')
),
div({class: 'fullline'}),
div({class: 'fullwidth'},
div({class: 'loading'},
div({}),
div({}),
div({}),
div({})
)
),
span({class: 'message ctext', style: 'padding-top: 10px'})
)
)
)
document.body.replaceWith(new_body)
if (data.posts.length < 10) {
document.getElementById('load').remove()
}
}
var isself = false
var page = 0
const data = {
self: {},
user: {},
users: {},
posts: []
}
async function load(id) {
if (id === undefined) {
id = data.user.user_id
}
const posts = (await loadusersposts(id, page)).json
if (posts == undefined) {
posts = []
}
if (posts.length < 1) {
let el = document.getElementsByClassName('loadp')[0]
if (el) {
el.remove()
}
} else {
page++
}
const batch = Array.from(new Set(crawl('user_id', posts))).filter(id => data.users[id] == undefined)
if (!isself) {
batch.push(id)
}
if (batch.length != 0) {
const users = (await loadusers(batch)).json
if (users == undefined) {
users = []
}
for (const user of users) {
data.users[user.user_id] = user
}
}
return posts
}
async function init() {
let request = await loadself()
if (request.status === 429) {
let new_body =
body({},
...header(false, false)
)
document.body.replaceWith(new_body)
throw new Error("Rate limited");
}
if (request.json == undefined) {
location.href = '/login'
return
}
data.self = request.json;
data.users[data.self.user_id] = data.self
var params = {};
for (const [key, value] of new URLSearchParams(location.search)) {
params[key] = value
}
let id;
if (params.id !== undefined && !isNaN(params.id)) {
id = parseInt(params.id);
} else {
id = data.self.user_id
}
isself = id === data.self.user_id
const posts = await load(id)
data.posts.push(... posts)
data.user = data.users[id]
render()
}
init()