Compare commits

..

No commits in common. "59c9acdc9e8d14d10d27cba35f6aef2a515e6db0" and "508af367045ac1890f9691f0e5bd5bab95f74019" have entirely different histories.

10 changed files with 157 additions and 197 deletions

View file

@ -1,11 +1,14 @@
<template>
<div>
<Loading v-if="loading" />
<NuxtPage />
</div>
</template>
<script lang="ts" setup>
const loading = useState("loading");
</script>
<style>
@ -15,6 +18,7 @@ body {
box-sizing: border-box;
color: rgb(190, 190, 190);
background-color: rgb(30, 30, 30);
height: 100%;
margin: 0;
}

View file

@ -1,6 +1,6 @@
<template>
<div id="message-area">
<div id="messages" ref="messagesElement">
<div id="messages">
<Message v-for="message of messages" :username="displayNames[message.user_uuid]" :text="message.message"
:timestamp="uuidToTimestamp(message.uuid)" format="12" />
</div>
@ -29,7 +29,7 @@ if (messagesRes && props.reverse) {
messagesRes.reverse();
}
const messages = ref<MessageResponse[]>([]);
const messages = ref(messagesRes ?? []);
const displayNames = ref<Record<string, string>>({});
@ -37,18 +37,6 @@ const route = useRoute();
const messageInput = ref<string>();
const messagesElement = ref<HTMLDivElement>();
if (messagesRes) messages.value = messagesRes;
const displayNamesArr: Record<string, string> = {};
for (const message of messages.value) {
if (!displayNamesArr[message.user_uuid]) {
const displayName = await getDisplayName(message.user_uuid);
displayNamesArr[message.user_uuid] = displayName;
}
}
displayNames.value = displayNamesArr;
const accessToken = useCookie("access_token").value;
const apiBase = useCookie("api_base").value;
const { refresh } = useAuth();
@ -100,7 +88,14 @@ function sendMessage(e: Event) {
}
onMounted(async () => {
messagesElement.value?.scrollTo({ top: messagesElement.value.scrollHeight });
const displayNamesArr: Record<string, string> = {};
for (const message of messages.value) {
if (!displayNamesArr[message.user_uuid]) {
const displayName = await getDisplayName(message.user_uuid);
displayNamesArr[message.user_uuid] = displayName;
}
}
displayNames.value = displayNamesArr;
});
</script>
@ -122,9 +117,17 @@ onMounted(async () => {
#message-box {
border: 1px solid rgb(70, 70, 70);
padding-bottom: 1dvh;
padding-top: 1dvh;
margin-bottom: 1dvh;
height: 7%;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
}
#message-form {
height: 50%;
width: 100%;
}
#message-input {

View file

@ -60,21 +60,17 @@ export const useAuth = () => {
async function refresh() {
console.log("refreshing");
const res = await fetchWithApi("/auth/refresh", {
method: "POST"
}) as any;
console.log("finished refreshing:", res);
if (res.access_token) {
accessToken.value = res.access_token;
console.log("set new access token");
} else {
console.log("refresh didn't return access token");
}
const res = await fetchWithApi("/auth/refresh", {
method: "POST"
}) as any;
console.log("finished refreshing:", res);
accessToken.value = res?.access_token;
console.log("set new access token");
}
async function fetchUser() {
if (!accessToken.value) return;
console.log("fetchuser access token:", accessToken.value);
console.log("fetchuser access token:", accessToken.value);
const res = await fetchWithApi("/users/me") as UserResponse;
user.value = res;
return user.value;

View file

@ -1,55 +1,55 @@
<template>
<NuxtLayout>
<div id="root-container" style="margin-top: 5dvh;">
<div id="main-container">
<div v-if="!instanceUrl">
<div v-if="instanceError" style="color: red;">
{{ instanceError }}
</div>
<form @submit="selectInstance">
<div>
<label for="instance-url">Instance URL</label>
<br>
<input type="url" name="instance-url" id="instance-url" required v-model="instanceUrlInput">
</div>
<div>
<button type="submit">Next</button>
</div>
</form>
<Loading v-if="!mounted" />
<div v-else id="root-container" style="margin-top: 5dvh;">
<div id="main-container">
<div v-if="!instanceUrl">
<div v-if="instanceError" style="color: red;">
{{ instanceError }}
</div>
<div v-else id="auth-form-container">
<slot />
<form @submit="selectInstance">
<div>
<label for="instance-url">Instance URL</label>
<br>
<input type="url" name="instance-url" id="instance-url" required v-model="instanceUrlInput">
</div>
<div>
<button type="submit">Next</button>
</div>
</form>
</div>
<div v-else id="auth-form-container">
<slot />
</div>
<div v-if="auth.accessToken.value">
You're logged in!
<form @submit="logout">
<div>
<label for="logout-password">Password</label>
<br>
<input type="password" name="logout-password" id="logout-password" v-model="form.password" required>
</div>
<div>
<button type="submit">Log out</button>
</div>
</form>
<div>
<button @click="refresh">Refresh</button>
</div>
<div v-if="auth.accessToken.value">
You're logged in!
<form @submit="logout">
<div>
<label for="logout-password">Password</label>
<br>
<input type="password" name="logout-password" id="logout-password" v-model="form.password" required>
</div>
<div>
<button type="submit">Log out</button>
</div>
</form>
<div>
<button @click="refresh">Refresh</button>
</div>
<div>
<button @click="showUser">Show user</button>
</div>
<div>
<button @click="getUser">Get me</button>
</div>
<div>
<button @click="showUser">Show user</button>
</div>
<div>
<button @click="getUser">Get me</button>
</div>
</div>
</div>
</NuxtLayout>
</div>
</template>
<script lang="ts" setup>
import { FetchError } from 'ofetch';
const mounted = ref(false);
const redirectTo = useRoute().query.redirect_to;
const apiVersion = useRuntimeConfig().public.apiVersion;
@ -64,6 +64,7 @@ if (auth.accessToken.value) {
}
onMounted(() => {
mounted.value = true;
const cookie = useCookie("instance_url").value;
instanceUrl.value = cookie;
console.log(cookie);

View file

@ -1,6 +1,5 @@
<template>
<Loading v-show="loading" />
<div :class="{ hidden: loading, visible: !loading }" id="client-root">
<div id="client-root">
<div id="homebar">
<div class="homebar-item">
main bar
@ -22,8 +21,6 @@
<script lang="ts" setup>
const loading = useState("loading", () => false);
const servers = [
{
name: "Test",
@ -93,21 +90,11 @@ function sendMessage(e: Event) {
<style>
#client-root {
/* border: 1px solid white; */
height: 100dvh;
height: 100%;
display: grid;
grid-template-columns: 1fr 4fr 18fr 4fr;
grid-template-rows: 4dvh auto;
text-align: center;
}
.hidden {
opacity: 0%;
}
.visible {
opacity: 100%;
transition-duration: 500ms;
}
#homebar {
@ -127,6 +114,7 @@ function sendMessage(e: Event) {
#__nuxt {
display: flex;
flex-flow: column;
height: 100%;
}
.grid-column {

View file

@ -1,6 +1,5 @@
export default defineNuxtRouteMiddleware(async (to, from) => {
console.log("to.path:", to.path);
const loading = useState("loading");
const accessToken = useCookie("access_token").value;
if (["/login", "/register"].includes(to.path)) {
if (accessToken) {
@ -10,15 +9,9 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
};
if (!accessToken) {
loading.value = true;
console.log("set loading to true");
const { refresh } = useAuth();
console.log("hi");
await refresh();
const query = new URLSearchParams();
query.set("redirect_to", to.path);
loading.value = false;
console.log("set loading to false");
return await navigateTo("/login" + (query ?? ""));
return await navigateTo("/login");
}
})

View file

@ -10,19 +10,7 @@ export default defineNuxtConfig({
E.g.: baseURL set to "/web" would host at https://gorb.app/web
Default is "/" (aka root), which hosts at https://gorb.app/
*/
baseURL: "/",
head: {
title: 'Gorb',
// this is purely used to embed in that other chat app, and similar stuff
meta: [
{ property: 'og:title', content: 'Gorb' },
{ property: 'og:description', content: 'Gorb is an open-source (and eventually federated) chat platform where you can join and chat in servers, chat privately in DMs, and more.' },
{ property: 'og:url', content: 'https://gorb.app/web' },
{ property: 'og:type', content: 'website' },
{ property: 'og:site_name', content: 'Gorb' },
{ property: 'theme-color', content: "#df5f0b" }
]
}
baseURL: "/web"
},
runtimeConfig: {
public: {

View file

@ -123,10 +123,10 @@ async function register(e: Event) {
e.preventDefault();
console.log("Sending registration data");
try {
await auth.register(form.username, form.email, form.password);
return await navigateTo(query.redirect_to);
await auth.register(form.username, form.email, form.password);
return await navigateTo(query.redirect_to);
} catch (error) {
console.error("Error registering:", error);
console.error("Error registering:", error);
}
//return navigateTo(redirectTo ? redirectTo as string : useAppConfig().baseURL as string);
}

View file

@ -39,20 +39,25 @@
const route = useRoute();
const loading = useState("loading");
const server: GuildResponse | undefined = await fetchWithApi(`servers/${route.params.serverId}`);
const channels: ChannelResponse[] | undefined = await fetchWithApi(
`servers/${route.params.serverId}/channels`
);
const channel: ChannelResponse | undefined = await fetchWithApi(
route.path
);
const channelUrlPath = `servers/${route.params.serverId}/channels/${route.params.channelId}`;
const server = ref<GuildResponse | undefined>();
const channels = ref<ChannelResponse[] | undefined>();
const channel = ref<ChannelResponse | undefined>();
console.log("channel:", channel);
const showInvitePopup = ref(false);
import type { ChannelResponse, GuildResponse, MessageResponse } from "~/types/interfaces";
//const servers = await fetchWithApi("/servers") as { uuid: string, name: string, description: string }[];
//console.log("channelid: servers:", servers);
//console.log("servers:", servers);
const members = [
{
id: "3287484395",
@ -101,24 +106,6 @@ const members = [
}
];
onMounted(async () => {
loading.value = true;
console.log("channelid: set loading to true");
server.value = await fetchWithApi(`servers/${route.params.serverId}`);
channels.value = await fetchWithApi(
`servers/${route.params.serverId}/channels`
);
channel.value = await fetchWithApi(
route.path
);
console.log("channelid: channel:", channel);
await sleep(3000);
loading.value = false;
console.log("channelid: set loading to false");
});
function showServerSettings() { }
function toggleInvitePopup(e: Event) {

View file

@ -9,74 +9,74 @@ export default async <T>(path: string, options: NitroFetchOptions<string> = {})
path = path.slice(0, path.lastIndexOf("/"));
}
console.log("formatted path:", path);
const accessToken = useCookie("access_token");
console.log("access token:", accessToken.value);
const apiBase = useCookie("api_base").value;
const apiVersion = useRuntimeConfig().public.apiVersion;
console.log("heyoooo")
console.log("apiBase:", apiBase);
if (!apiBase) {
console.log("no api base");
return;
}
console.log("path:", path)
const { revoke, refresh } = useAuth();
console.log("access token 2:", accessToken.value);
const accessToken = useCookie("access_token");
console.log("access token:", accessToken.value);
const apiBase = useCookie("api_base").value;
const apiVersion = useRuntimeConfig().public.apiVersion;
console.log("heyoooo")
console.log("apiBase:", apiBase);
if (!apiBase) {
console.log("no api base");
return;
}
console.log("path:", path)
const { revoke, refresh } = useAuth();
console.log("access token 2:", accessToken.value);
let headers: HeadersInit = {};
let headers: HeadersInit = {};
if (accessToken.value) {
headers = {
...options.headers,
"Authorization": `Bearer ${accessToken.value}`
};
} else {
headers = {
...options.headers
};
}
if (accessToken.value) {
headers = {
...options.headers,
"Authorization": `Bearer ${accessToken.value}`
};
} else {
headers = {
...options.headers
};
}
let reauthFailed = false;
while (!reauthFailed) {
try {
console.log("fetching:", URL.parse(apiBase + path));
const res = await $fetch<T>(URL.parse(apiBase + path)!.href, {
...options,
headers,
credentials: "include"
});
let reauthFailed = false;
while (!reauthFailed) {
try {
console.log("fetching:", URL.parse(apiBase + path));
const res = await $fetch<T>(URL.parse(apiBase + path)!.href, {
...options,
headers,
credentials: "include"
});
return res;
} catch (error: any) {
console.error("Error fetching resource");
if (error?.response?.status === 401) {
console.log("Error status is 401");
if (!path.startsWith("/auth/refresh")) {
console.log("Path is not refresh endpoint");
try {
console.log("Trying to refresh");
await refresh();
console.log("Successfully refreshed token");
} catch (error: any) {
console.log("Failed to refresh token");
if (error?.response?.status === 401) {
console.log("Refresh returned 401");
reauthFailed = true;
console.log("Revoking");
await revoke();
console.log("Redirecting to login");
await navigateTo("/login");
console.log("redirected");
return;
}
}
} else {
console.log("Path is refresh endpoint, throwing error");
throw error;
}
}
console.log("throwing error");
throw error;
}
}
return res;
} catch (error: any) {
console.error("Error fetching resource");
if (error?.response?.status === 401) {
console.log("Error status is 401");
if (!path.startsWith("/auth/refresh")) {
console.log("Path is not refresh endpoint");
try {
console.log("Trying to refresh");
await refresh();
console.log("Successfully refreshed token");
} catch (error: any) {
console.log("Failed to refresh token");
if (error?.response?.status === 401) {
console.log("Refresh returned 401");
reauthFailed = true;
console.log("Revoking");
await revoke();
console.log("Redirecting to login");
await navigateTo("/login");
console.log("redirected");
return;
}
}
} else {
console.log("Path is refresh endpoint, throwing error");
throw error;
}
}
console.log("throwing error");
throw error;
}
}
}