Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Websockets on FileView #29

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA/nqSs2DZmox+sRNR9d9XdaO3C2yJABIO5gdJlBcswNI=
-----END PUBLIC KEY-----"

PUBLIC_PUSHER_APP_KEY="3a4575271634ad5a09ef"
PUBLIC_PUSHER_APP_CLUSTER="eu"

PUBLIC_LIVEBLOCKS_API_KEY="pk_dev_Nwp6X3J4wQWoOKenVZfTTo20uVznlY5ir2_W95bx0RjleqvW7LKKMlPbCZISFsYI"
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"flowbite-typography": "^1.0.3",
"jose": "^4.15.1",
"nanostores": "^0.9.3",
"pusher-js": "^8.3.0",
"tailwind-scrollbar": "^3.0.5",
"tailwindcss": "^3.3.3",
"typescript": "^5.2.2",
Expand Down
60 changes: 0 additions & 60 deletions src/components/TestForm.vue

This file was deleted.

55 changes: 43 additions & 12 deletions src/components/item/Browser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ import { fetchFromApi } from '@lib/helpers';

// Stores
import { useStore } from '@nanostores/vue';
import { addItem, itemsStore } from '@stores/items';
import { addItem, removeItem, itemsStore } from '@stores/items';
import { isModalOpen } from '@stores/modal';

// Components
Expand All @@ -90,6 +90,10 @@ const props = defineProps({
type: Object as PropType<FolderType>,
required: false,
},
user: {
type: Object as PropType<User>,
required: true,
},
});

const fileBrowserContextMenu = ref<InstanceType<typeof ContextMenu>>();
Expand All @@ -109,7 +113,7 @@ const toasts = ref<{ message: string; type: ToastType }[]>([]);
/**
* Items
*/
import { ItemClass } from '@lib/items/items';
import { ItemClass, type ItemType } from '@lib/items/items';
import { ItemFactory } from '@lib/items/factory';

import NoFiles from './file/NoFiles.vue';
Expand Down Expand Up @@ -192,16 +196,6 @@ async function uploadFiles(e: Event) {
Array.from(fileInput.files).forEach(async (file) => {
try {
await FileClass.create(file, props.modelValue ?? null);

// TODO: replace waiting 1 second with websocket
setTimeout(async () => {
await getItems();

toasts.value.push({
message: `File ${file.name} uploaded`,
type: ToastType.Success,
});
}, 1000);
} catch (error) {
toasts.value.push({
message: `Failed to upload file ${file.name}`,
Expand All @@ -223,4 +217,41 @@ const createDocsModal = ref<InstanceType<typeof CreateDocsModal>>();
const docs = computed(() => {
return Object.values(items.value).filter((item) => item instanceof DocsClass) as DocsClass[];
});

/**
* Live Updates
*/
import { getFolderChannel } from '@lib/pusher';

const channel = getFolderChannel(props.user.id, props.modelValue?.id);
channel.bind('update', (data: ItemType) => {
if (!ItemClass.isItem(data)) return;

const item = ItemFactory.getItemFromObject(data);

if (item === null) return;

const isNew = items.value[item.id] === undefined;
const isOwner = item.ownerId === props.user.id;

if (isNew && isOwner) {
// TODO: Fix toasts
toasts.value.push({
message: `${item.name} has been created`,
type: ToastType.Success,
});
}

addItem(item);
});

channel.bind('delete', (data: ItemType) => {
if (!ItemClass.isItem(data)) return;

const item = ItemFactory.getItemFromObject(data);

if (item === null) return;

removeItem(item);
});
</script>
4 changes: 4 additions & 0 deletions src/components/item/ShareItemModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ async function getItem() {

rawItem.ItemSharing.forEach(
(sharing: { id: number; user: { id: number; name: string; email: string } }) => {
if (sharing.user.id === rawItem.owner.id) {
return;
}

usersWithAccess.value.push({
id: sharing.user.id,
sharingId: sharing.id,
Expand Down
7 changes: 6 additions & 1 deletion src/components/item/docs/EditModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,15 @@ async function updateFile() {
// TODO: Show success toast

close(false);
} catch (e) {}
} catch (e) {
console.error('Error: ' + e);
}
}

function open() {
docs.value = {
name: props.docs.name,
};
modal.value?.open();
}

Expand Down
3 changes: 3 additions & 0 deletions src/components/item/file/EditModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ async function updateFile() {
}

function open() {
file.value = {
name: props.file.name,
};
modal.value?.open();
}

Expand Down
4 changes: 4 additions & 0 deletions src/components/item/folder/EditModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ async function updateFolder() {
}

function open() {
folder.value = {
name: props.folder.name,
color: props.folder.color,
};
modal.value?.open();
}

Expand Down
3 changes: 3 additions & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// <reference types="astro/client" />

interface User {
id: number;
name: string;
email: string;
}
Expand All @@ -13,6 +14,8 @@ interface ImportMetaEnv {
readonly PUBLIC_LOCAL_DEVELOPMENT_API_URL: string | undefined;
readonly JWT_PUBLIC_KEY: string;
readonly NODE_BUILD: boolean | undefined;
readonly PUBLIC_PUSHER_APP_KEY: string;
readonly PUBLIC_PUSHER_APP_CLUSTER: string;
}

interface ImportMeta {
Expand Down
8 changes: 4 additions & 4 deletions src/lang/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default {
submit: 'Edit',
},
action: {
create: 'Upload fil',
create: 'Upload file',
edit: 'Rename file',
share: 'Share',
delete: 'Delete',
Expand Down Expand Up @@ -112,12 +112,12 @@ export default {
submit: 'Edit',
},
action: {
create: 'Create Docs',
edit: 'Rename Docs',
create: 'Create docs',
edit: 'Rename docs',
share: 'Share',
delete: 'Delete',
openInNewTab: 'Open in new tab',
confirmDelete: 'Are you sure you want to delete this Docs?',
confirmDelete: 'Are you sure you want to delete this docs?',
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion src/lib/items/docs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ItemClass, type ItemType } from './items';
import { type FolderType } from './folders';
import { api } from '@lib/helpers';
import { api, fetchFromApi } from '@lib/helpers';

export class DocsClass extends ItemClass {
private _text: string;
Expand Down
15 changes: 15 additions & 0 deletions src/lib/pusher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Pusher from 'pusher-js';

Pusher.logToConsole = true;

const pusher = new Pusher(import.meta.env.PUBLIC_PUSHER_APP_KEY, {
cluster: import.meta.env.PUBLIC_PUSHER_APP_CLUSTER,
});

const getFolderChannel = (userId: number, itemId: number | null | undefined) => {
const channelName = itemId ? `browser-folder-${itemId}` : `browser-root-${userId}`;

return pusher.subscribe(channelName);
};

export { pusher, getFolderChannel };
2 changes: 1 addition & 1 deletion src/middleware/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const user = defineMiddleware(async ({ locals, request, redirect }, next)
}

// Otherwise, set the user data in the locals.
locals.user = userResponse as User;
locals.user = { id: locals.userId, ...userResponse } as User;

return next();
});
Expand Down
2 changes: 1 addition & 1 deletion src/pages/u/folder/[id].astro
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ const user = Astro.locals.user as User;

<LayoutSidebar user={user}>
<div class="h-screen">
<Browser modelValue={folder} client:only />
<Browser modelValue={folder} user={user} client:only />
</div>
</LayoutSidebar>
2 changes: 1 addition & 1 deletion src/pages/u/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ const user = Astro.locals.user as User;

<LayoutSidebar user={user}>
<div class="h-screen">
<Browser modelValue={{}} client:only />
<Browser modelValue={{}} user={user} client:only />
</div>
</LayoutSidebar>