Skip to content
This repository has been archived by the owner on Dec 2, 2024. It is now read-only.

[1.9] GC Invites & GC Bans #198

Closed
wants to merge 13 commits into from
3 changes: 2 additions & 1 deletion src/lib/Post.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,8 @@
editing = true;
await tick();
editContentInput.value =
post.unfiltered_content || post.content;
post.unfiltered_content ||
post.content;
editContentInput.focus();
autoresize(editContentInput);
}}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/Report.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import {authHeader} from "./stores.js";
import {apiUrl} from "./urls.js";
import { adminPermissions, hasPermission } from "./bitField.js";
import {adminPermissions, hasPermission} from "./bitField.js";
import * as modals from "./modals.js";

import {goto} from "@roxi/routify";
Expand Down
28 changes: 28 additions & 0 deletions src/lib/RescalebleImage.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script>
export let src;
export let alt = "";

import {onMount} from "svelte";

let img;
onMount(() => {
img.classList.add("rescaleble-image");
img.style.backgroundImage = `url(${src})`;
img.title = alt;
});
</script>

<div id="img" bind:this={img} {...$$restProps} />

<style>
.rescaleble-image {
display: flex;
flex-grow: 1;
min-width: 25%;
height: 500px;
background-image: url("https://meower.org/assets/cat_disks.jpg");
background-repeat: no-repeat;
object-fit: contain;
background-size: contain;
}
</style>
Empty file added src/lib/getBannedUsers.js
Empty file.
38 changes: 38 additions & 0 deletions src/lib/modals/chats/BanMember.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script>
import {authHeader} from "./../../stores.js";
import Modal from "../../Modal.svelte";
import * as modals from "../../modals.js";
import {chat} from "../../stores";
import {apiUrl} from "../../urls";

export let modalData;

let {username} = modalData;

let reason = "";
</script>

<Modal on:close={modals.closeLastModal}>
<h2 slot="header">Remove {username}</h2>

<div slot="default">
Are you sure you want to ban {username} from this chat?
<form
on:submit|preventDefault={() => {
fetch(`${apiUrl}chats/${$chat._id}/bans/${username}`, {
method: "PUT",
headers: {
...$authHeader,
},
body: reason,
});
modals.closeLastModal();
}}
>
<label for="reason">Reason</label>
<input type="text" id="reason" bind:value={reason} />

<button type="submit">Ban</button>
</form>
</div>
</Modal>
81 changes: 81 additions & 0 deletions src/lib/modals/chats/BannedMembers.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<script>
import Member from "./../../Member.svelte";
import {authHeader, chat} from "./../../stores.js";
import {apiUrl} from "./../../urls.js";
import Modal from "../../Modal.svelte";
import * as modals from "../../modals";
import Spinner from "../../Spinner.svelte";
import Container from "../../Container.svelte";

async function fetchBannedMembers() {
const resp = await fetch(`${apiUrl}chats/${$chat._id}/bans`, {
headers: $authHeader,
});
if (!resp.ok) {
if (resp.status === 429) {
throw new Error("Too many requests! Try again later.");
}
throw new Error("Response code is not OK; code is " + resp.status);
}
$chat.banned_users = (await resp.json()).bans;
}
</script>

<Modal on:close={modals.closeLastModal}>
<h2 slot="header">Banned Users</h2>
<div slot="default">
{#await fetchBannedMembers()}
<Spinner />
{:then _}
{#each $chat.banned_users as member}
<Container>
<Member member={member.username} owner={false} />
<div class="inline">
<p>Reason: {member.message}</p>

<button
class="delete"
on:click={() => {
fetch(
`${apiUrl}chats/${$chat._id}/bans/${member.username}`,
{
method: "DELETE",
headers: $authHeader,
}
);
modals.closeLastModal();
}}>Unban</button
>
</div>
</Container>
{/each}
{/await}
</div>
</Modal>

<style>
p {
display: flex;
justify-content: center;
text-align: center;
}

.delete {
justify-content: right;
flex: right;
height: 100%;
}

.inline {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: left;
vertical-align: middle;
}

.inline p {
justify-self: center;
align-self: center;
}
</style>
11 changes: 11 additions & 0 deletions src/lib/modals/chats/GCMember.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import * as modals from "../../modals.js";

import {params, goto} from "@roxi/routify";
import BanMember from "./BanMember.svelte";

export let modalData;

Expand Down Expand Up @@ -48,6 +49,16 @@
>
Make owner of chat
</button>
<button
class="long"
on:click={() => {
modals.replaceLastModal(BanMember, {
username,
});
}}
>
Ban user from chat
</button>
{/if}
</div>
</Modal>
Expand Down
85 changes: 85 additions & 0 deletions src/lib/settings/chats/Banned.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<script>
import {authHeader} from "../../stores.js";
import {chat} from "../../stores.js";
import {apiUrl} from "../../urls.js";
import Container from "../../Container.svelte";
import ProfileView from "../../ProfileView.svelte";
import Member from "../../Member.svelte";

let bans = [];
async function fetchBans() {
const resp = await fetch(`${apiUrl}chats/${$chat._id}/bans`, {
headers: $authHeader,
})
if (!resp.ok) {
throw new Error("Failed to fetch bans");
}
const data = await resp.json();
bans = data.bans;

}
</script>

<Container>
<h1>Banned Users</h1>
<hr>
{#await fetchBans()}
<p>Loading...</p>
{:then}
{#if bans.length === 0}
<p>No banned users</p>
{:else}
{#each bans as ban}

<Container><div class="inline">
<Member member={ban.username} owner={false} />
<p class="right_align">Reason: {ban.message} </p>
<button
class="unban"
on:click={
async () => {
const resp = await fetch(`${apiUrl}chats/${$chat._id}/bans/${ban.username}`, {
method: "DELETE",
headers: $authHeader,
});
if (!resp.ok) {
throw new Error("Failed to unban user");
}
bans = bans.filter((b) => b.username !== ban.username);
}
}>Unban</button>

</div>
</Container>

{/each}
{/if}
{:catch e}
<p>{e.message}</p>
{/await}
</Container>

<style>
.unban {
justify-content: right;
flex-direction: column;

}

.inline {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: left;
vertical-align: middle;
}

.inline p {
flex: right;
justify-self: right;
}

:global(.inline .member) {
max-width: 25%;
}
</style>
97 changes: 97 additions & 0 deletions src/lib/settings/chats/Invites.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<script>
import {chat, authHeader} from "../../stores.js";
import Spinner from "../../Spinner.svelte";
import {apiUrl} from "../../urls";
import Modal from "../../Modal.svelte";
import * as modals from "../../modals";
import {writable} from "svelte/store";
import Container from "../../Container.svelte";

if (!$chat.invites) $chat.invites = [];
// @ts-ignore
if (typeof $chat.invites != "Array") $chat.invites = [];

async function fetchInvites() {
let data = await (
await fetch(`${apiUrl}chats/${$chat._id}/invites`, {
headers: $authHeader,
})
).json();
console.log(data);
$chat.invites = data.invites;
}
</script>

<Container>
<h1>Invites</h1>

{#await fetchInvites()}
<Spinner />
{/await}
<hr />

{#each $chat.invites as invite}
<div class="inline">
<a
href="{window.location.protocol}://{window.location.host}/invite/{invite._id}"
target="_blank"
>
{window.location.protocol}//{window.location.host}/invite/{invite._id}
</a>
<div class="delete">
<button
class="right_align"
on:click|preventDefault={() => {
fetch(`${apiUrl}chats/invites/${invite._id}`, {
method: "DELETE",
headers: $authHeader,
});
}}
>
Revoke Invite
</button>
</div>
</div>
{/each}
<hr />
<button
on:click|preventDefault={async () => {
let invite = await (
await fetch(`${apiUrl}chats/${$chat._id}/invites`, {
method: "POST",
headers: $authHeader,
})
).json();

$chat.invites = [
...$chat.invites,
{_id: invite.invite, chat_id: $chat._id},
];
}}>Create Invite</button
>
</Container>

<style>
.right_align {
align-self: right;
}

.delete {
justify-content: right;
flex: right;
margin-top: 1rem;
}

.inline {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: left;
vertical-align: middle;
}

.inline a {
justify-self: center;
align-self: center;
}
</style>
Loading