✨ Channel establish
This commit is contained in:
		
							
								
								
									
										61
									
								
								src/components/chat/channels/ChannelDeletion.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/components/chat/channels/ChannelDeletion.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| <template> | ||||
|   <v-card title="Delete a realm" class="min-h-[540px]" :loading="loading"> | ||||
|     <template #text> | ||||
|       You are deleting a channel | ||||
|       <b>{{ channels.related.delete_to?.name }}</b> <br /> | ||||
|       All messaging belonging to this channel will be deleted and never appear again. Are you confirm? | ||||
|     </template> | ||||
|     <template #actions> | ||||
|       <div class="w-full flex justify-end"> | ||||
|         <v-btn color="grey-darken-3" @click="channels.show.delete = false">Not really</v-btn> | ||||
|         <v-btn color="error" :disabled="loading" @click="deletePost">Yes</v-btn> | ||||
|       </div> | ||||
|     </template> | ||||
|   </v-card> | ||||
|  | ||||
|   <v-snackbar v-model="success" :timeout="3000">The realm has been deleted.</v-snackbar> | ||||
|  | ||||
|   <!-- @vue-ignore --> | ||||
|   <v-snackbar v-model="error" :timeout="5000">Something went wrong... {{ error }}</v-snackbar> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { request } from "@/scripts/request" | ||||
| import { getAtk } from "@/stores/userinfo" | ||||
| import { useChannels } from "@/stores/channels" | ||||
| import { useRoute, useRouter } from "vue-router" | ||||
| import { ref } from "vue" | ||||
|  | ||||
| const route = useRoute() | ||||
| const router = useRouter() | ||||
| const channels = useChannels() | ||||
|  | ||||
| const emits = defineEmits(["relist"]) | ||||
|  | ||||
| const error = ref<string | null>(null) | ||||
| const success = ref(false) | ||||
| const loading = ref(false) | ||||
|  | ||||
| async function deletePost() { | ||||
|   const target = channels.related.delete_to | ||||
|   const url = `/api/channels/${target.id}` | ||||
|  | ||||
|   loading.value = true | ||||
|   const res = await request("messaging", url, { | ||||
|     method: "DELETE", | ||||
|     headers: { Authorization: `Bearer ${await getAtk()}` } | ||||
|   }) | ||||
|   if (res.status !== 200) { | ||||
|     error.value = await res.text() | ||||
|   } else { | ||||
|     success.value = true | ||||
|     channels.show.delete = false | ||||
|     channels.related.delete_to = null | ||||
|     emits("relist") | ||||
|     if (route.name?.toString()?.startsWith("realm")) { | ||||
|       router.push({ name: "explore" }) | ||||
|     } | ||||
|   } | ||||
|   loading.value = false | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										77
									
								
								src/components/chat/channels/ChannelEditor.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/components/chat/channels/ChannelEditor.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| <template> | ||||
|   <v-card title="Establish a channel" prepend-icon="mdi-pound-box" class="min-h-[540px]" :loading="loading"> | ||||
|     <v-form @submit.prevent="submit"> | ||||
|       <v-card-text> | ||||
|         <v-text-field label="Alias" variant="outlined" density="comfortable" hint="Must be unique" | ||||
|                       v-model="data.alias" /> | ||||
|         <v-text-field label="Name" variant="outlined" density="comfortable" v-model="data.name" /> | ||||
|         <v-textarea label="Description" variant="outlined" density="comfortable" v-model="data.description" /> | ||||
|       </v-card-text> | ||||
|       <v-card-actions> | ||||
|         <v-spacer></v-spacer> | ||||
|  | ||||
|         <v-btn type="reset" color="grey-darken-3" @click="channels.show.editor = false">Cancel</v-btn> | ||||
|         <v-btn type="submit" :disabled="loading">Save</v-btn> | ||||
|       </v-card-actions> | ||||
|     </v-form> | ||||
|   </v-card> | ||||
|  | ||||
|   <!-- @vue-ignore --> | ||||
|   <v-snackbar v-model="error" :timeout="5000">Something went wrong... {{ error }}</v-snackbar> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { ref, watch } from "vue" | ||||
| import { getAtk } from "@/stores/userinfo" | ||||
| import { request } from "@/scripts/request" | ||||
| import { useChannels } from "@/stores/channels" | ||||
|  | ||||
| const emits = defineEmits(["relist"]) | ||||
|  | ||||
| const channels = useChannels() | ||||
|  | ||||
| const error = ref<null | string>(null) | ||||
| const loading = ref(false) | ||||
|  | ||||
| const data = ref({ | ||||
|   alias: "", | ||||
|   name: "", | ||||
|   description: "" | ||||
| }) | ||||
|  | ||||
| async function submit(evt: SubmitEvent) { | ||||
|   const form = evt.target as HTMLFormElement | ||||
|   const payload = data.value | ||||
|   if (!payload.name) return | ||||
|  | ||||
|   const url = channels.related.edit_to ? `/api/channels/${channels.related.edit_to?.id}` : "/api/channels" | ||||
|   const method = channels.related.edit_to ? "PUT" : "POST" | ||||
|  | ||||
|   loading.value = true | ||||
|   const res = await request("messaging", url, { | ||||
|     method: method, | ||||
|     headers: { "Content-Type": "application/json", Authorization: `Bearer ${await getAtk()}` }, | ||||
|     body: JSON.stringify(payload) | ||||
|   }) | ||||
|   if (res.status !== 200) { | ||||
|     error.value = await res.text() | ||||
|   } else { | ||||
|     emits("relist") | ||||
|     form.reset() | ||||
|     channels.done = true | ||||
|     channels.show.editor = false | ||||
|     channels.related.edit_to = null | ||||
|   } | ||||
|   loading.value = false | ||||
| } | ||||
|  | ||||
| watch( | ||||
|   channels.related, | ||||
|   (val) => { | ||||
|     if (val.edit_to) { | ||||
|       data.value = JSON.parse(JSON.stringify(val.edit_to)) | ||||
|     } | ||||
|   }, | ||||
|   { immediate: true } | ||||
| ) | ||||
| </script> | ||||
							
								
								
									
										42
									
								
								src/components/chat/channels/ChannelList.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/components/chat/channels/ChannelList.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| <template> | ||||
|   <v-list-group value="channels"> | ||||
|     <template #activator="{ props }"> | ||||
|       <v-list-item | ||||
|         v-bind="props" | ||||
|         prepend-icon="mdi-chat" | ||||
|         title="Channels" | ||||
|       /> | ||||
|     </template> | ||||
|  | ||||
|     <v-list-item | ||||
|       v-for="item in channels.available" | ||||
|       exact | ||||
|       append-icon="mdi-pound-box" | ||||
|       :to="{ name: 'chat.channel', params: { channel: item.alias } }" | ||||
|       :title="item.name" | ||||
|     /> | ||||
|  | ||||
|     <v-list-item | ||||
|       append-icon="mdi-plus" | ||||
|       title="Create a channel" | ||||
|       variant="plain" | ||||
|       :disabled="!id.userinfo.isLoggedIn" | ||||
|       @click="createChannel" | ||||
|     /> | ||||
|   </v-list-group> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { useUserinfo } from "@/stores/userinfo" | ||||
| import { useRealms } from "@/stores/realms" | ||||
| import { useChannels } from "@/stores/channels" | ||||
|  | ||||
| const id = useUserinfo() | ||||
| const channels = useChannels() | ||||
|  | ||||
| function createChannel() { | ||||
|   channels.related.edit_to = null | ||||
|   channels.related.delete_to = null | ||||
|   channels.show.editor = true | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										16
									
								
								src/components/chat/channels/ChannelTools.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/components/chat/channels/ChannelTools.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| <template> | ||||
|   <v-bottom-sheet class="max-w-[480px]" v-model="channels.show.editor"> | ||||
|     <channel-editor @relist="channels.list" /> | ||||
|   </v-bottom-sheet> | ||||
|   <v-bottom-sheet class="max-w-[480px]" v-model="channels.show.delete"> | ||||
|     <channel-deletion @relist="channels.list" /> | ||||
|   </v-bottom-sheet> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { useChannels } from "@/stores/channels" | ||||
| import ChannelEditor from "@/components/chat/channels/ChannelEditor.vue" | ||||
| import ChannelDeletion from "@/components/chat/channels/ChannelDeletion.vue" | ||||
|  | ||||
| const channels = useChannels() | ||||
| </script> | ||||
| @@ -3,7 +3,7 @@ | ||||
|     <template #text> | ||||
|       You are deleting a realm | ||||
|       <b>{{ realms.related.delete_to?.name }}</b> <br /> | ||||
|       All posts belonging to this domain will be deleted and never appear again. Are you confirm? | ||||
|       All posts belonging to this realm will be deleted and never appear again. Are you confirm? | ||||
|     </template> | ||||
|     <template #actions> | ||||
|       <div class="w-full flex justify-end"> | ||||
|   | ||||
| @@ -1,27 +1,29 @@ | ||||
| <template> | ||||
|   <v-list density="comfortable"> | ||||
|     <v-list-subheader> | ||||
|       Realms | ||||
|       <v-badge color="warning" content="Alpha" inline /> | ||||
|     </v-list-subheader> | ||||
|   <v-list-group value="realms"> | ||||
|     <template #activator="{ props }"> | ||||
|       <v-list-item | ||||
|         v-bind="props" | ||||
|         prepend-icon="mdi-account-box-multiple" | ||||
|         title="Realms" | ||||
|       /> | ||||
|     </template> | ||||
|  | ||||
|     <v-list-item | ||||
|       v-for="item in realms.available" | ||||
|       exact | ||||
|       prepend-icon="mdi-account-multiple" | ||||
|       append-icon="mdi-account-multiple" | ||||
|       :to="{ name: 'realms.page', params: { realmId: item.id } }" | ||||
|       :title="item.name" | ||||
|     /> | ||||
|  | ||||
|     <v-divider v-if="realms.available.length > 0" class="border-opacity-75 my-2" /> | ||||
|  | ||||
|     <v-list-item | ||||
|       prepend-icon="mdi-plus" | ||||
|       append-icon="mdi-plus" | ||||
|       title="Create a realm" | ||||
|       variant="plain" | ||||
|       :disabled="!id.userinfo.isLoggedIn" | ||||
|       @click="createRealm" | ||||
|     /> | ||||
|   </v-list> | ||||
|   </v-list-group> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| <template> | ||||
|   <v-bottom-sheet v-model="realms.show.editor"> | ||||
|   <v-bottom-sheet class="max-w-[480px]" v-model="realms.show.editor"> | ||||
|     <realm-editor @relist="realms.list" /> | ||||
|   </v-bottom-sheet> | ||||
|   <v-bottom-sheet v-model="realms.show.delete"> | ||||
|   <v-bottom-sheet class="max-w-[480px]" v-model="realms.show.delete"> | ||||
|     <realm-deletion @relist="realms.list" /> | ||||
|   </v-bottom-sheet> | ||||
| </template> | ||||
|   | ||||
| @@ -3,6 +3,9 @@ | ||||
|     <v-system-bar v-show="ui.safeArea.top > 0" color="primary" :order="1" :height="ui.safeArea.top" /> | ||||
|  | ||||
|     <router-view /> | ||||
|  | ||||
|     <realm-tools /> | ||||
|     <channel-tools /> | ||||
|   </v-app> | ||||
| </template> | ||||
|  | ||||
| @@ -10,6 +13,8 @@ | ||||
| import { onMounted, ref } from "vue" | ||||
| import { Capacitor } from "@capacitor/core" | ||||
| import { useUI } from "@/stores/ui" | ||||
| import RealmTools from "@/components/realms/RealmTools.vue" | ||||
| import ChannelTools from "@/components/chat/channels/ChannelTools.vue" | ||||
|  | ||||
| const ui = useUI() | ||||
|  | ||||
|   | ||||
| @@ -34,13 +34,18 @@ | ||||
|         </div> | ||||
|       </v-toolbar> | ||||
|  | ||||
|       <div class="flex-grow-1"> | ||||
|       <v-list class="flex-grow-1" :opened="drawerMini ? [] : expanded" @update:opened="(val) => expanded = val"> | ||||
|         <channel-list /> | ||||
|         <v-divider class="border-opacity-75 my-2" /> | ||||
|         <realm-list /> | ||||
|       </div> | ||||
|       </v-list> | ||||
|  | ||||
|       <!-- User info --> | ||||
|       <v-list class="border-opacity-15 h-[64px]" style="border-top-width: thin" | ||||
|               :style="`margin-bottom: ${safeAreaBottom}`"> | ||||
|       <v-list | ||||
|         class="border-opacity-15 h-[64px]" | ||||
|         style="border-top-width: thin" | ||||
|         :style="`margin-bottom: ${safeAreaBottom}`" | ||||
|       > | ||||
|         <v-list-item :subtitle="username" :title="nickname"> | ||||
|           <template #prepend> | ||||
|             <v-avatar icon="mdi-account-circle" :image="id.userinfo.data?.picture" /> | ||||
| @@ -52,8 +57,12 @@ | ||||
|               </template> | ||||
|  | ||||
|               <v-list density="compact"> | ||||
|                 <v-list-item title="Solarpass" prepend-icon="mdi-passport-biometric" target="_blank" | ||||
|                              :href="passportUrl" /> | ||||
|                 <v-list-item | ||||
|                   title="Solarpass" | ||||
|                   prepend-icon="mdi-passport-biometric" | ||||
|                   target="_blank" | ||||
|                   :href="passportUrl" | ||||
|                 /> | ||||
|               </v-list> | ||||
|             </v-menu> | ||||
|  | ||||
| @@ -87,16 +96,15 @@ | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { computed, ref } from "vue" | ||||
| import { useEditor } from "@/stores/editor" | ||||
| import { useUserinfo } from "@/stores/userinfo" | ||||
| import { useWellKnown } from "@/stores/wellKnown" | ||||
| import { useUI } from "@/stores/ui" | ||||
| import PostTools from "@/components/publish/PostTools.vue" | ||||
| import RealmTools from "@/components/realms/RealmTools.vue" | ||||
| import RealmList from "@/components/realms/RealmList.vue" | ||||
| import NotificationList from "@/components/NotificationList.vue" | ||||
| import ChannelList from "@/components/chat/channels/ChannelList.vue" | ||||
|  | ||||
| const ui = useUI() | ||||
| const expanded = ref<string[]>(["channels"]) | ||||
|  | ||||
| const safeAreaTop = computed(() => { | ||||
|   return `${ui.safeArea.top}px` | ||||
|   | ||||
| @@ -37,14 +37,12 @@ | ||||
|   </v-fab> | ||||
|  | ||||
|   <post-tools /> | ||||
|   <realm-tools /> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import PostTools from "@/components/publish/PostTools.vue" | ||||
| import RealmTools from "@/components/realms/RealmTools.vue" | ||||
| import { useEditor } from "@/stores/editor" | ||||
| import { useUserinfo } from "@/stores/userinfo" | ||||
| import PostTools from "@/components/publish/PostTools.vue" | ||||
|  | ||||
| const id = useUserinfo() | ||||
| const editor = useEditor() | ||||
|   | ||||
| @@ -13,7 +13,7 @@ export const useChannels = defineStore("channels", () => { | ||||
|     delete: false | ||||
|   }) | ||||
|  | ||||
|   const related_to = reactive<{ edit_to: any; delete_to: any }>({ | ||||
|   const related = reactive<{ edit_to: any; delete_to: any }>({ | ||||
|     edit_to: null, | ||||
|     delete_to: null | ||||
|   }) | ||||
| @@ -64,5 +64,5 @@ export const useChannels = defineStore("channels", () => { | ||||
|     socket.close() | ||||
|   } | ||||
|  | ||||
|   return { done, show, related_to, available, current, messages, list, connect, disconnect } | ||||
|   return { done, show, related, available, current, messages, list, connect, disconnect } | ||||
| }) | ||||
| @@ -11,7 +11,7 @@ export const useRealms = defineStore("realms", () => { | ||||
|     delete: false | ||||
|   }) | ||||
|  | ||||
|   const related_to = reactive<{ edit_to: any; delete_to: any }>({ | ||||
|   const related = reactive<{ edit_to: any; delete_to: any }>({ | ||||
|     edit_to: null, | ||||
|     delete_to: null | ||||
|   }) | ||||
| @@ -31,5 +31,5 @@ export const useRealms = defineStore("realms", () => { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return { done, show, related: related_to, available, list } | ||||
|   return { done, show, related, available, list } | ||||
| }) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user