Compare commits
14 commits
508af36704
...
59c9acdc9e
Author | SHA1 | Date | |
---|---|---|---|
59c9acdc9e | |||
3b1581d950 | |||
a324cc9300 | |||
a439f9481a | |||
379b85db4e | |||
751bdcfd9a | |||
a5f0e19716 | |||
7ad2b6f299 | |||
6548f9329e | |||
e6bff0042d | |||
585e79dac6 | |||
93b7bf9154 | |||
19fcccfb5b | |||
9981bc4158 |
10 changed files with 197 additions and 157 deletions
4
app.vue
4
app.vue
|
@ -1,14 +1,11 @@
|
|||
<template>
|
||||
<div>
|
||||
<Loading v-if="loading" />
|
||||
<NuxtPage />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
const loading = useState("loading");
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -18,7 +15,6 @@ body {
|
|||
box-sizing: border-box;
|
||||
color: rgb(190, 190, 190);
|
||||
background-color: rgb(30, 30, 30);
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div id="message-area">
|
||||
<div id="messages">
|
||||
<div id="messages" ref="messagesElement">
|
||||
<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(messagesRes ?? []);
|
||||
const messages = ref<MessageResponse[]>([]);
|
||||
|
||||
const displayNames = ref<Record<string, string>>({});
|
||||
|
||||
|
@ -37,6 +37,18 @@ 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();
|
||||
|
@ -88,14 +100,7 @@ function sendMessage(e: Event) {
|
|||
}
|
||||
|
||||
onMounted(async () => {
|
||||
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;
|
||||
messagesElement.value?.scrollTo({ top: messagesElement.value.scrollHeight });
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -117,17 +122,9 @@ 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 {
|
||||
|
|
|
@ -60,17 +60,21 @@ export const useAuth = () => {
|
|||
|
||||
async function refresh() {
|
||||
console.log("refreshing");
|
||||
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");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -1,55 +1,55 @@
|
|||
<template>
|
||||
<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 }}
|
||||
<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>
|
||||
</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>
|
||||
</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 v-else id="auth-form-container">
|
||||
<slot />
|
||||
</div>
|
||||
<div>
|
||||
<button @click="showUser">Show user</button>
|
||||
</div>
|
||||
<div>
|
||||
<button @click="getUser">Get me</button>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NuxtLayout>
|
||||
</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,7 +64,6 @@ if (auth.accessToken.value) {
|
|||
}
|
||||
|
||||
onMounted(() => {
|
||||
mounted.value = true;
|
||||
const cookie = useCookie("instance_url").value;
|
||||
instanceUrl.value = cookie;
|
||||
console.log(cookie);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div id="client-root">
|
||||
<Loading v-show="loading" />
|
||||
<div :class="{ hidden: loading, visible: !loading }" id="client-root">
|
||||
<div id="homebar">
|
||||
<div class="homebar-item">
|
||||
main bar
|
||||
|
@ -21,6 +22,8 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
|
||||
const loading = useState("loading", () => false);
|
||||
|
||||
const servers = [
|
||||
{
|
||||
name: "Test",
|
||||
|
@ -90,11 +93,21 @@ function sendMessage(e: Event) {
|
|||
<style>
|
||||
#client-root {
|
||||
/* border: 1px solid white; */
|
||||
height: 100%;
|
||||
height: 100dvh;
|
||||
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 {
|
||||
|
@ -114,7 +127,6 @@ function sendMessage(e: Event) {
|
|||
#__nuxt {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.grid-column {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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) {
|
||||
|
@ -9,9 +10,15 @@ 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();
|
||||
return await navigateTo("/login");
|
||||
const query = new URLSearchParams();
|
||||
query.set("redirect_to", to.path);
|
||||
loading.value = false;
|
||||
console.log("set loading to false");
|
||||
return await navigateTo("/login" + (query ?? ""));
|
||||
}
|
||||
})
|
||||
|
|
|
@ -10,7 +10,19 @@ 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: "/web"
|
||||
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" }
|
||||
]
|
||||
}
|
||||
},
|
||||
runtimeConfig: {
|
||||
public: {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -39,25 +39,20 @@
|
|||
|
||||
const route = useRoute();
|
||||
|
||||
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 loading = useState("loading");
|
||||
|
||||
const channelUrlPath = `servers/${route.params.serverId}/channels/${route.params.channelId}`;
|
||||
|
||||
console.log("channel:", channel);
|
||||
const server = ref<GuildResponse | undefined>();
|
||||
const channels = ref<ChannelResponse[] | undefined>();
|
||||
const channel = ref<ChannelResponse | undefined>();
|
||||
|
||||
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("servers:", servers);
|
||||
//console.log("channelid: servers:", servers);
|
||||
const members = [
|
||||
{
|
||||
id: "3287484395",
|
||||
|
@ -106,6 +101,24 @@ 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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue