Compare commits

..

2 Commits

Author SHA1 Message Date
a2beb45302 💄 Optimized attachment viewer
🐛 Fix lightbox safe area issue
2024-03-30 01:05:47 +08:00
5a1ef55126 🐛 Bug fixes
 Collapsable sidebar
2024-03-30 00:57:16 +08:00
7 changed files with 74 additions and 28 deletions

1
ios/.gitignore vendored
View File

@ -11,3 +11,4 @@ capacitor-cordova-ios-plugins
# Generated Config files # Generated Config files
App/App/capacitor.config.json App/App/capacitor.config.json
App/App/config.xml App/App/config.xml
App/App.xcarchive

View File

@ -48,6 +48,7 @@
"typescript": "~5.4.0", "typescript": "~5.4.0",
"unocss": "^0.58.7", "unocss": "^0.58.7",
"vite": "^5.1.6", "vite": "^5.1.6",
"vite-plugin-pwa": "^0.19.7",
"vue-tsc": "^2.0.6" "vue-tsc": "^2.0.6"
} }
} }

View File

@ -3,10 +3,11 @@
Attached {{ props.attachments.length }} attachment(s) Attached {{ props.attachments.length }} attachment(s)
</v-chip> </v-chip>
<v-card v-else variant="outlined" class="max-w-[540px]"> <v-card v-else variant="outlined" class="max-w-[540px] max-h-[720px]">
<v-carousel hide-delimiters progress="primary" show-arrows="hover" height="100%"> <v-carousel hide-delimiter-background height="100%" :show-arrows="false">
<v-carousel-item v-for="item in attachments"> <v-carousel-item v-for="item in attachments">
<img v-if="item.type === 1" :src="getUrl(item)" class="cursor-zoom-in" @click="openLightbox" /> <img v-if="item.type === 1" :src="getUrl(item)" :alt="item.filename" class="cursor-zoom-in"
@click="openLightbox" />
<video v-if="item.type === 2" controls class="w-full"> <video v-if="item.type === 2" controls class="w-full">
<source :src="getUrl(item)" /> <source :src="getUrl(item)" />
</video> </video>
@ -18,7 +19,14 @@
<vue-easy-lightbox teleport="#app" :visible="lightbox" :imgs="[getUrl(current)]" @hide="lightbox = false"> <vue-easy-lightbox teleport="#app" :visible="lightbox" :imgs="[getUrl(current)]" @hide="lightbox = false">
<template v-slot:close-btn="{ close }"> <template v-slot:close-btn="{ close }">
<v-btn class="fixed left-2 top-2" icon="mdi-close" variant="text" color="white" @click="close" /> <v-btn
class="fixed left-2 top-2"
icon="mdi-close"
variant="text"
color="white"
:style="`margin-top: ${safeAreaTop}`"
@click="close"
/>
</template> </template>
</vue-easy-lightbox> </vue-easy-lightbox>
</v-card> </v-card>
@ -27,16 +35,23 @@
<script setup lang="ts"> <script setup lang="ts">
import { buildRequestUrl } from "@/scripts/request" import { buildRequestUrl } from "@/scripts/request"
import { computed, ref } from "vue" import { computed, ref } from "vue"
import { useUI } from "@/stores/ui"
import VueEasyLightbox from "vue-easy-lightbox" import VueEasyLightbox from "vue-easy-lightbox"
const props = defineProps<{ attachments: any[]; overview?: boolean }>() const props = defineProps<{ attachments: any[]; overview?: boolean }>()
const ui = useUI()
const lightbox = ref(false) const lightbox = ref(false)
const focus = ref(0) const focus = ref(0)
const current = computed(() => props.attachments[focus.value]) const current = computed(() => props.attachments[focus.value])
const canLightbox = computed(() => current.value.type === 1) const canLightbox = computed(() => current.value.type === 1)
const safeAreaTop = computed(() => {
return `${ui.safeArea.top}px`
})
function getUrl(item: any) { function getUrl(item: any) {
return item.external_url ? item.external_url : buildRequestUrl("interactive", `/api/attachments/o/${item.file_id}`) return item.external_url ? item.external_url : buildRequestUrl("interactive", `/api/attachments/o/${item.file_id}`)
} }

View File

@ -1,15 +1,15 @@
<template> <template>
<v-bottom-sheet v-model="editor.show.comment" eager> <v-bottom-sheet class="max-w-[480px]" v-model="editor.show.comment" eager>
<comment-editor /> <comment-editor />
</v-bottom-sheet> </v-bottom-sheet>
<v-bottom-sheet v-model="editor.show.moment" eager> <v-bottom-sheet class="max-w-[480px]" v-model="editor.show.moment" eager>
<moment-editor /> <moment-editor />
</v-bottom-sheet> </v-bottom-sheet>
<v-bottom-sheet v-model="editor.show.article" eager> <v-bottom-sheet v-model="editor.show.article" eager>
<article-editor /> <article-editor />
</v-bottom-sheet> </v-bottom-sheet>
<v-bottom-sheet v-model="editor.show.delete" eager> <v-bottom-sheet class="max-w-[480px]" v-model="editor.show.delete" eager>
<post-deletion /> <post-deletion />
</v-bottom-sheet> </v-bottom-sheet>
</template> </template>

View File

@ -54,13 +54,11 @@ async function upload(file?: any) {
const data = new FormData() const data = new FormData()
if (!file) { if (!file) {
if (!picked.value) return file = picked.value[0]
data.set("attachment", picked.value[0])
} else {
data.set("attachment", file)
} }
data.set("hashcode", await calculateHashCode(picked.value[0])) data.set("attachment", file)
data.set("hashcode", await calculateHashCode(file))
emits("update:uploading", true) emits("update:uploading", true)
const res = await request("interactive", "/api/attachments", { const res = await request("interactive", "/api/attachments", {

View File

@ -1,10 +1,29 @@
<template> <template>
<v-navigation-drawer v-model="drawerOpen" color="grey-lighten-5" width="320" :order="0" floating> <v-navigation-drawer
v-model="drawerOpen"
color="grey-lighten-5"
width="320"
:rail="drawerMini"
:rail-width="58"
:order="0"
@click="drawerMini = false"
>
<div class="flex flex-col h-full"> <div class="flex flex-col h-full">
<div class="flex items-center px-3 pb-2.5 border-opacity-15" style="border-bottom-width: thin" <div class="flex items-center justify-between px-3 pb-2.5 border-opacity-15 min-h-[64px]"
:style="`padding-top: max(${safeAreaTop}, 16px)`"> style="border-bottom-width: thin"
<img src="/favicon.png" width="36" height="36" class="block" /> :style="`padding-top: max(${safeAreaTop}, 10px)`">
<div class="ms-6 font-medium">Solar Network</div> <div class="flex items-center">
<img src="/favicon.png" alt="Logo" width="36" height="36" class="block" />
<div v-show="!drawerMini" class="ms-6 font-medium">Solar Network</div>
</div>
<v-btn
v-show="!drawerMini"
icon="mdi-arrow-collapse-left"
size="small"
variant="text"
@click.stop="drawerMini = true"
/>
</div> </div>
<div class="flex-grow-1"> <div class="flex-grow-1">
@ -39,7 +58,7 @@
<v-app-bar height="64" color="primary" scroll-behavior="hide" :order="2" flat> <v-app-bar height="64" color="primary" scroll-behavior="hide" :order="2" flat>
<div class="max-md:px-5 md:px-12 flex flex-grow-1 items-center"> <div class="max-md:px-5 md:px-12 flex flex-grow-1 items-center">
<v-app-bar-nav-icon variant="text" @click.stop="toggleDrawer" /> <v-app-bar-nav-icon variant="text" @click.stop="drawerOpen = !drawerOpen" />
<router-link :to="{ name: 'explore' }"> <router-link :to="{ name: 'explore' }">
<h2 class="ml-2 text-lg font-500">Solian</h2> <h2 class="ml-2 text-lg font-500">Solian</h2>
@ -124,10 +143,7 @@ const passportUrl = computed(() => {
meta.readWellKnown() meta.readWellKnown()
const drawerOpen = ref(true) const drawerOpen = ref(true)
const drawerMini = ref(false)
function toggleDrawer() {
drawerOpen.value = !drawerOpen.value
}
</script> </script>
<style scoped> <style scoped>

View File

@ -1,13 +1,28 @@
import { fileURLToPath, URL } from "node:url" import { fileURLToPath, URL } from "node:url"
import { defineConfig } from "vite" import { defineConfig } from "vite"
import { VitePWA as vitePWA } from "vite-plugin-pwa"
import vue from "@vitejs/plugin-vue" import vue from "@vitejs/plugin-vue"
import vueJsx from "@vitejs/plugin-vue-jsx" import vueJsx from "@vitejs/plugin-vue-jsx"
import unocss from "unocss/vite" import unocss from "unocss/vite"
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue(), vueJsx(), unocss()], plugins: [
vue(),
vueJsx(),
unocss(),
vitePWA({
registerType: "autoUpdate",
useCredentials: true,
manifest: {
name: "Solian",
short_name: "Solian",
description: "The Solar Network entrypoint.",
theme_color: "#4b5094",
},
})
],
resolve: { resolve: {
alias: { alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)) "@": fileURLToPath(new URL("./src", import.meta.url))