diff --git a/package.json b/package.json index 27dc9bf..ae2d9fb 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "frangipane-client", "private": true, - "version": "0.1.0", - "backendVersion": "1.0.2", + "version": "1.0.0", + "backendVersion": "1.0.3", "type": "module", "scripts": { "dev": "vite", diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6c3c727..8141a53 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "frangipane", - "version": "0.1.0", + "version": "1.0.0", "identifier": "com.strawberries.frangipane", "build": { "beforeDevCommand": "yarn dev", diff --git a/src/App.vue b/src/App.vue index 18b52fb..1a5cd7e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,16 +1,16 @@ diff --git a/src/api/rooms.ts b/src/api/rooms.ts index 6d8abe3..5fc8e87 100644 --- a/src/api/rooms.ts +++ b/src/api/rooms.ts @@ -1,42 +1,65 @@ import { apiFetch } from './client' -import type { Room, RoomInvite } from '../types' +import { UserProfile, type Room, type RoomInvite } from '../types' export function fetchRooms() { - return apiFetch(`/rooms`) + return apiFetch(`/rooms`) } export function fetchRoomInfo(uuid: string) { - return apiFetch(`/rooms/${uuid}`) + return apiFetch(`/rooms/${uuid}`) } export function createRoom(name: string, global: boolean) { - return apiFetch('/rooms', { - method: 'POST', - body: JSON.stringify({ name, global }), - }) + return apiFetch('/rooms', { + method: 'POST', + body: JSON.stringify({ name, global }), + }) } export function fetchRoomInvites() { - return apiFetch('/rooms/invites') + return apiFetch('/rooms/invites') } export function sendRoomInvite(receiverUsername: string, roomUuid: string) { - return apiFetch('/rooms/invite', { - method: 'POST', - body: JSON.stringify({ receiver_username: receiverUsername, room_uuid: roomUuid }), - }); + return apiFetch('/rooms/invite', { + method: 'POST', + body: JSON.stringify({ receiver_username: receiverUsername, room_uuid: roomUuid }), + }); } export function acceptRoomInvite(senderUuid: string, roomUuid: string) { - return apiFetch('/rooms/join', { - method: 'POST', - body: JSON.stringify({ sender_uuid: senderUuid, room_uuid: roomUuid }), - }) + return apiFetch('/rooms/join', { + method: 'POST', + body: JSON.stringify({ sender_uuid: senderUuid, room_uuid: roomUuid }), + }) } export function declineRoomInvite(senderUuid: string, roomUuid: string) { - return apiFetch('/rooms/decline', { - method: 'POST', - body: JSON.stringify({ sender_uuid: senderUuid, room_uuid: roomUuid }), - }) + return apiFetch('/rooms/decline', { + method: 'POST', + body: JSON.stringify({ sender_uuid: senderUuid, room_uuid: roomUuid }), + }) +} + +export function leaveRoom(roomUuid: string) { + return apiFetch(`/rooms/${roomUuid}/leave`, { + method: 'POST' + }) +} + +export function deleteRoom(roomUuid: string) { + return apiFetch(`/rooms/${roomUuid}/delete`, { + method: 'DELETE' + }) +} + +export function transferOwnership(roomUuid: string, newOwnerUuid: string) { + return apiFetch('/rooms/transfer-ownership', { + method: 'POST', + body: JSON.stringify({ room_uuid: roomUuid, new_owner_uuid: newOwnerUuid }), + }) +} + +export function listMembers(roomUuid: string) { + return apiFetch(`/rooms/${roomUuid}/members`) } diff --git a/src/base.css b/src/base.css index d9e856e..042e927 100644 --- a/src/base.css +++ b/src/base.css @@ -24,6 +24,7 @@ body, --muted: #9aa0aa; --accent: #f27aa3; --accent-hover: #ff91b3; + --accent-second: #96CDFB; --border: #2a2f3b; --error: #ff5050; --radius: 8px; @@ -174,6 +175,15 @@ i:hover { margin: 30px; } +.avatar { + width: 35px; + height: 35px; + border-radius: 50%; + object-fit: cover; + border: 1px solid var(--border); + flex-shrink: 0; +} + @media (hover: hover) { i:hover { color: var(--text); diff --git a/src/components/ChatWindow.vue b/src/components/ChatWindow.vue index 8f3cca3..be95d1f 100644 --- a/src/components/ChatWindow.vue +++ b/src/components/ChatWindow.vue @@ -1,39 +1,55 @@ diff --git a/src/components/ConfirmModal.vue b/src/components/ConfirmModal.vue new file mode 100644 index 0000000..6d7bc1d --- /dev/null +++ b/src/components/ConfirmModal.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/components/MessageList.vue b/src/components/MessageList.vue index 485ebb1..87c7c90 100644 --- a/src/components/MessageList.vue +++ b/src/components/MessageList.vue @@ -2,7 +2,7 @@
  • - +
    {{ m.sender }}
    {{ m.sent_at }}
    @@ -74,15 +74,6 @@ ul { padding: 5px 18px; } -.sender-avatar { - width: 35px; - height: 35px; - border-radius: 50%; - object-fit: cover; - border: 1px solid var(--border); - flex-shrink: 0; -} - .message.is-me { align-self: flex-end; align-items: flex-end; diff --git a/src/components/RoomDetailsModal.vue b/src/components/RoomDetailsModal.vue new file mode 100644 index 0000000..c34f717 --- /dev/null +++ b/src/components/RoomDetailsModal.vue @@ -0,0 +1,280 @@ + + + + + diff --git a/src/components/RoomList.vue b/src/components/RoomList.vue index c6aed89..09d9250 100644 --- a/src/components/RoomList.vue +++ b/src/components/RoomList.vue @@ -11,14 +11,18 @@ -
    +

    {{ $t('chat-room-list-connecting') }}

    +
    + +
    +

    {{ $t('chat-room-list-empty') }}

    -
    +
    @@ -48,21 +52,27 @@ const route = useRoute(); const showCreate = ref(false); const rooms = ref([]); const unreadCounts = ref>({}); +const isLoading = ref(true); async function refreshRooms() { - const fetchedRooms = await fetchRooms(); - rooms.value = fetchedRooms; + isLoading.value = true; - fetchedRooms.forEach(room => { - console.log(`Unread count for room ${room.name}: ${room.unread_count}`); + try { + const fetchedRooms = await fetchRooms(); + rooms.value = fetchedRooms; - // If the room isn't the currently active one, store the count - if (room.unread_count && route.params.uuid !== room.uuid) { - unreadCounts.value[room.uuid] = room.unread_count; - } else { - unreadCounts.value[room.uuid] = 0; - } - }); + fetchedRooms.forEach(room => { + if (room.unread_count && route.params.uuid !== room.uuid) { + unreadCounts.value[room.uuid] = room.unread_count; + } else { + unreadCounts.value[room.uuid] = 0; + } + }); + } catch (error) { + console.error("Failed to refresh rooms", error); + } finally { + isLoading.value = false; + } } const incrementUnread = (roomUuid: string) => { @@ -72,7 +82,7 @@ const incrementUnread = (roomUuid: string) => { unreadCounts.value[roomUuid] = current + 1; }; -defineExpose({ incrementUnread }); +defineExpose({ incrementUnread, refreshRooms }); watch( () => route.params.uuid, @@ -85,7 +95,6 @@ watch( ); onMounted(async () => { - // rooms.value = await fetchRooms(); await refreshRooms() }); @@ -111,6 +120,7 @@ onMounted(async () => { left: 50%; transform: translate(-50%, -50%); margin: 0; + width: 100%; } .wait-msg { @@ -162,7 +172,6 @@ onMounted(async () => { } .rooms-header h2 { - /* font-size: 1rem; */ margin: 0; margin-left: 45px; } @@ -189,7 +198,6 @@ onMounted(async () => { } .room-item.active { - /* border: 1px solid var(--border); */ background: var(--panel-accent); color: var(--accent); } diff --git a/src/locales/en.ftl b/src/locales/en.ftl index 54494b6..3a62b8d 100644 --- a/src/locales/en.ftl +++ b/src/locales/en.ftl @@ -25,6 +25,7 @@ auth-error-email-invalid = Please enter a valid email address ## Chat page chat-no-room = Select a room to start talking +chat-no-messages = No messages yet. Say hi! chat-input-placeholder = type a message chat-invite-title = Invite People chat-invite-receiver = Receiver username @@ -32,8 +33,16 @@ chat-invite-friend-too = Also send a friend request chat-invite-send = Send chat-invite-username-placeholder = username chat-room-list-title = Rooms +chat-room-list-empty = No rooms found chat-room-list-connecting = Connecting... chat-room-owner = by {$owner} +chat-room-global = Global room +chat-room-members = Members +chat-room-actions-leave = Leave Room +chat-room-actions-leave-confirm = Are you sure you want to leave this room? +chat-room-actions-delete = Delete Room +chat-room-actions-delete-confirm = Are you sure you want to delete this room? This cannot be undone. +chat-room-actions-ownership = Transfer Ownership chat-create-title = Create room chat-create-name = Room name chat-create-name-placeholder = room name @@ -95,6 +104,9 @@ warning-wrongversion-dismiss = I know what I'm doing ## Shared shared-cancel = Cancel +shared-close = Close shared-error = An error occurred shared-save = Save shared-updating = Updating +shared-delete = Delete +shared-leave = Leave diff --git a/src/locales/fr.ftl b/src/locales/fr.ftl index 99f1890..3f4a204 100644 --- a/src/locales/fr.ftl +++ b/src/locales/fr.ftl @@ -25,8 +25,10 @@ auth-error-email-invalid = Veuillez entrer une adresse email valide ## Chat page chat-no-room = Sélectionnez un salon pour commencer à discuter +chat-no-messages = Pas encore de messages. Dites bonjour ! chat-input-placeholder = tapez un message chat-invite-title = Inviter des gens +chat-room-list-empty = Aucun salon trouvé chat-invite-receiver = Nom du destinataire chat-invite-friend-too = Envoyer aussi une demande d'ami chat-invite-send = Envoyer @@ -34,6 +36,13 @@ chat-invite-username-placeholder = nom d'utilisateur chat-room-list-title = Salons chat-room-list-connecting = Connexion... chat-room-owner = par {$owner} +chat-room-global = Salon global +chat-room-members = Membres +chat-room-actions-leave = Quitter le Salon +chat-room-actions-leave-confirm = Voulez-vous vraiment quitter ce salon? +chat-room-actions-delete = Supprimer le Salon +chat-room-actions-delete-confirm = Voulez-vous vraiment supprimer ce salon? C'est irréversible. +chat-room-actions-ownership = Transférer la Propriété chat-create-title = Créer un salon chat-create-name = Nom du salon chat-create-name-placeholder = nom du salon @@ -93,6 +102,9 @@ warning-wrongversion-dismiss = Je sais ce que je fais ## Shared shared-cancel = Annuler +shared-close = Fermer shared-error = Une erreur est survenue shared-save = Enregistrer shared-updating = Mise à jour... +shared-delete = Supprimer +shared-leave = Quitter diff --git a/src/main.ts b/src/main.ts index 2c2bd77..1d2a342 100644 --- a/src/main.ts +++ b/src/main.ts @@ -28,9 +28,9 @@ async function init() { init() -// export const API = 'http://127.0.0.1:8080' -export const API = 'http://192.168.1.183:8080' +export const API = 'http://127.0.0.1:8080' +// export const API = 'http://192.168.1.183:8080' // export const API = 'https://alatreon.org/frangipane' -// export const API_WS = 'ws://127.0.0.1:8080/ws' -export const API_WS = 'ws://192.168.1.183:8080/ws' +export const API_WS = 'ws://127.0.0.1:8080/ws' +// export const API_WS = 'ws://192.168.1.183:8080/ws' // export const API_WS = 'wss://alatreon.org/frangipane/ws' diff --git a/src/pages/ChatPage.vue b/src/pages/ChatPage.vue index 9d73e19..df1ac65 100644 --- a/src/pages/ChatPage.vue +++ b/src/pages/ChatPage.vue @@ -13,27 +13,39 @@
    - +